Draw a randomly colored Sierpinski octagon in C#


[Sierpinski octagon]

This example draws a randomly colored Sierpinski octagon. It’s basically the same as the example Draw a randomly colored Sierpinski pentagon in C# except it draws an octagon instead of a pentagon. See that example for most of the details.

There are two main differences between that example and this one. First, the new example uses the following code to set its scale factor.

// Scale factor for moving to smaller octagons.
private float size_scale = (float)(1.0 /
    (2.0 * (1 + Math.Cos(Math.PI / 180 * 45))));

The program adjusts the radius of the smaller octagons by this scale factor to make them fit properly. (This scale needs to change to different kinds of polygons.)

The second change is in the method that generates the points that make up the polygons. The following code shows the new version, which creates an octagon.

// Find the octagon's corners.
private PointF[] GetOctagonPoints(PointF center, float radius)
{
    PointF[] points = new PointF[8];
    double theta = -Math.PI / 2.0;
    double dtheta = 2.0 * Math.PI / 8.0;
    for (int i = 0; i < 8; i++)
    {
        points[i] = new PointF(
            center.X + (float)(radius * Math.Cos(theta)),
            center.Y + (float)(radius * Math.Sin(theta)));
        theta += dtheta;
    }
    return points;
}

This method simply loops the variable theta through the angles at which the octagon’s vertices lie and uses Math.Sin and Math.Cos to calculate the locations of the vertices.

The rest of the program is similar to the previous post. Download this example and see that one for more details.


Download Example   Follow me on Twitter   RSS feed   Donate




Posted in algorithms, fractals, graphics, recursion | Tagged , , , , , , , , , , | Leave a comment

Let the user draw lines in C#


[draw lines]

This example lets the user click and draw to draw lines. To make working with lines easier, the program uses the following Segment class.

class Segment
{
    public Pen Pen;
    public Point Point1, Point2;

    public Segment(Pen pen, Point point1, Point point2)
    {
        Pen = pen;
        Point1 = point1;
        Point2 = point2;
    }

    public void Draw(Graphics gr)
    {
        gr.DrawLine(Pen, Point1, Point2);
    }
}

This class simply stores a pen and the segment’s end points. The Draw method draws the segment on a Graphics object.

The program uses the following form-level variables to let the user draw lines.

private List<Segment> Segments = new List<Segment>();
private Segment NewSegment = null;

The Segments list holds Segment objects that were created in the past. NewSegment represents a new Segment while the user is drawing it. This variable is null when the user is not drawing a new segment.

Line drawing begins when the user presses the mouse down over the picCanvas PictureBox making the following event handler execute.

// Start drawing a new segment.
private void picCanvas_MouseDown(object sender, MouseEventArgs e)
{
    NewSegment = new Segment(Pens.Blue, e.Location, e.Location);
    picCanvas.Refresh();
}

This code sets NewSegment to a new Segment object with a blue pen. It sets both of the new segment’s end points to the mouse’s current location.

The method then refreshes the picCanvas PictureBox to make the following Paint event handler execute to display the new segment (and any old segments).

// Draw the segments.
private void picCanvas_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.Clear(picCanvas.BackColor);
    e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;

    // Draw existing segments.
    foreach (Segment segment in Segments)
        segment.Draw(e.Graphics);

    // Draw the new segment if there is one.
    if (NewSegment != null)
        NewSegment.Draw(e.Graphics);
}

This code clears the Graphics object and sets its SmoohingMode. It then loops through the objects in the Segments list and calls their Draw methods to make them draw themselves. Finally, if NewSegment isn’t null, the code calls that object’s Draw method to make it draw itself.

When the user moves the mouse over the picCanvas PictureBox, the following event handler executes.

// Continue drawing the new segment.
private void picCanvas_MouseMove(object sender, MouseEventArgs e)
{
    if (NewSegment == null) return;
    
    NewSegment.Point2 = e.Location;
    picCanvas.Refresh();
}

This method first checks whether NewSegment is null. If it is null, then the user is not drawing a new segment. In that case, the code simply returns.

If NewSegment is not null, the code updates the new segment’s second end point to the mouse’s current location. It then refreshes the PictureBox to make it redraw the segments to show the new one’s updated position.

When the user releases the mouse, the following event handler executes.

// Finish drawing the new segment.
private void picCanvas_MouseUp(object sender, MouseEventArgs e)
{
    if (NewSegment == null) return;

    NewSegment.Pen = Pens.Black;
    Segments.Add(NewSegment);
    NewSegment = null;
    picCanvas.Refresh();
}

Like the MouseMove event handler, this one checks whether NewSegment is null and returns if the user is not drawing a new segment. It then sets the new segment’s pen to black and adds it to the Segments list. It sets NewSegment to null to indicate that we are done drawing the new segment and then refreshes the PictureBox to redraw the lines.


Download Example   Follow me on Twitter   RSS feed   Donate




Posted in drawing, events, graphics | Tagged , , , , , , , , , , , | Leave a comment

Book review: Python for Kids: A Playful Introduction To Programming

[book review]

Over the years, I’ve read many thousands of books, some good and some not so good. Jason Briggs’ book Python for Kids: A Playful Introduction To Programming falls into the very exclusive category of books that I wish I had written. The book is written in a clear, understandable, non-threatening style that almost anyone should be able to follow. It includes cute pictures and enough humor to stay interesting for both kids and adults without becoming cloying. It covers everything a beginner needs to know to get started in Python, starting with how to download and install Python itself (for free). It then explains how to write programs, use variables of different types, use loops and ranges, make lists and tuples, create classes and objects, and of course drive a turtle.

Everything a beginner needs is there, so rather than summarizing the table of contents, I want to discuss a more important issue: who should read this book and how. I would recommend this book to any beginner, but that doesn’t mean everyone is ready to learn to program on his or her own. Every programming book covers some basics before it can show you how to do anything really fun. (You need to eat your vegetables before you can have dessert!) Some particularly younger readers may have trouble pushing through the first few chapters before reaching more interesting material.

For those who are less self-motivated, I recommend working with a partner. For example, a parent/child or grandparent/grandchild pair would be awesome! You might try taking turns teaching the chapters. “I’ll read ahead and teach you this chapter. Then you can do the same for the next one.” Working as a team would give you some quality non-screen time together and would lay the foundation for more serious programming later.

As for what age is appropriate for this kind of book, that depends entirely on those involved. I’ve known seven-year-olds who would have no trouble reading this book. Unfortunately, I’ve also known adults so thoroughly convinced that they could never learn to program a computer that they wouldn’t make it past the table of contents. (A parent/child team might work very well for that person.)

If you haven’t programmed before and want to give it a try, I highly recommend this book. If you have one or more special kids in your life who you think might be interested in programming, make it a group project. I can promise that it’ll be a lot of fun and, if you’re not careful, you’ll probably end up learning to program, too.

For information about this book at Amazon, click here.


Follow me on Twitter   RSS feed   Donate




Posted in books | Tagged , , , | Leave a comment

Use a standard Windows dialog to let the user select folders in C#

[select folders]

The .NET OpenFileDialog and SaveFileDialog are fairly full-featured. They’re a lot like Windows Explorer with some added file selection capabilities thrown in.

In contrast, the FolderBrowserDialog is pretty pathetic. It only lets you use a hierarchical tree-like display, doesn’t provide different views (such as Detail, List, and Large Icon), doesn’t allow you to search, and doesn’t let you type in parts of the folder’s path if you know them.

Although Windows itself uses a much more powerful file and folder selection dialog, Microsoft hasn’t yet given it to .NET developer. Once upon a time, Microsoft provided the Windows API Code Pack, which works in Windows Vista and later. Then, for no obvious reason, they removed the Code Pack and erased all evidence of its existence. (Sort of like a weird, nerdy version of Liam Neeson’s film “Unknown.”)

Fortunately, there are several libraries available at GitHub that can help. This link leads to a version of the Windows API Code Pack 1.1 posted by jamie-pate.

To install the Code Pack, follow the link and click the Download button. Extract the files from the downloaded zip file and put them somewhere safe where you won’t need to move them later.

Launch Visual Studio, start a new project, open the Project menu, and select Add Reference. On the Add Reference dialog, and click the Browse tab. Next, browse into the folder that you unzipped, enter the “binaries” folder, and select the following two files.

  • Microsoft.WindowsAPICodePack.dll
  • Microsoft.WindowsAPICodePack.Shell.dll

Now the program can use the Code Pack dialogs. To make using the dialog easier, include the following using directive:

using Microsoft.WindowsAPICodePack.Dialogs;

Now you can use the CommonOpenFileDialog or CommonSaveFileDialog components to display a file or folder selection dialog. This example uses the following code to let the user select a folder.

// Let the user select a folder.
private void btnSelect_Click(object sender, EventArgs e)
{
    CommonOpenFileDialog dialog = new CommonOpenFileDialog();
    dialog.InitialDirectory = txtFolder.Text;
    dialog.IsFolderPicker = true;
    if (dialog.ShowDialog() == CommonFileDialogResult.Ok)
    {
        txtFolder.Text = dialog.FileName;
    }
}

I once hoped that Micosoft would eventually include these dialogs with Visual Studio, or at least update the FolderBrowserDialog to something more usable. It’s been so long, however, that I think I’m going to have to let that dream die. It seems likely that we’ll be stuck using this old saved version of the Code Pack or some other dialogs written by other people for the foreseeable future.


Download Example   Follow me on Twitter   RSS feed   Donate




Posted in API, controls, files | Tagged , , , , , , , , , , , , , , , , | 13 Comments

Gary Beene’s gbUnSnarl game

[game]

Check out Gary Bene’s gbUnSnarl game. Your job is to drag the nodes in a network to unsnarl it.

Basically it asks you to find a way to rearrange a planar network so none of its edges intersect. Algorithms to prove that a network is planar are fairly complicated. The networks generated by the game are guaranteed to be planar, so there are always solutions. The only question is, “Can you find them?”


Follow me on Twitter   RSS feed   Donate




Posted in algorithms, games | Tagged , , , , , , , , | Leave a comment

Find happy numbers in C#


[happy numbers]

Before I show you the code, let me explain what happy numbers are.

Happy Numbers

To find happy numbers, start with any integer. Replace it with the sum of the squares off its digits. Repeat the process until the numbers repeat or reach the value 1 (after which the 1 repeats). Happy numbers are those that reach 1. Other values are unhappy or sad numbers.

For example, the following values show the happy sequences of numbers starting with 7.

72 = 49
42 + 92 = 97
92 + 72 = 130
12 + 32 + 02 = 10
12 + 02 = 1

This program graphs the places where the loops start and their lengths for happy numbers. For example, the equations above shows that the value 7 enters a loop after 5 steps and the loop has length 1 (because 1 just repeats).

Unhappy numbers eventually enter the loop 4, 16, 37, 58, 89, 145, 42, 20, 4, …

The program graphs the numbers’ starting points in red and the lengths of the cycles in blue. You can spot the happy numbers in the list on the left by looking for the ones with length equal to 1. The list highlights prime numbers in pink so you can pick out the happy primes.

Code

When you click the Go button, the program loops through values from 1 to the maximum value that you enter in the text box. For each value, the program calls the following FindHappyLoop method.

// Return the length and start position of the number's happy loop.
private List<int> FindHappyLoop(int num,
    out int loop_start, out int loop_length)
{
    List<int> list = new List<int>();
    list.Add(num);
    for (; ; )
    {
        string str = num.ToString();
        num = 0;
        foreach (char ch in str)
        {
            int digit = int.Parse(ch.ToString());
            num += digit * digit;
        }
        if (list.Contains(num))
        {
            loop_start = list.IndexOf(num);
            loop_length = list.Count - loop_start;
            return list;
        }
        list.Add(num);
    }
}

This method creates a list to hold the values in the number’s happy sequence. It then enters an infinite loop.

Inside the loop, the code converts the number into a string and then loops through its digits. It converts each digit into a number, squares it, and adds it to the variable num.

The final value of num is the next value in the number’s happy sequence. If that number is already in the sequence, the sequence has entered a loop. In that case, the method sets the loop’s start position and length and then returns.

The rest of the program is relatively straightforward, so I won’t show it here. Download the example to see additional details such as how the program builds the list on the left and how it draws the graph.


Download Example   Follow me on Twitter   RSS feed   Donate




Posted in algorithms, mathematics | Tagged , , , , , , , | Leave a comment

Draw words on a circle in WPF and C#

[draw words]

This example shows one way that you can draw words on a circle in WPF. Note that it does not show how to draw words where each character is rotated to follow the circle’s curve. Each word is rotated as a whole. That generally produces a good result for relatively small words such as the ones drawn here.

The following text shows the program’s control hierarchy created at design time. The text includes some of the controls’ properties to make it easier to identify the controls on the picture.

Window
    Grid Background="LightGreen"
        Label Name="lblZoom" Content="100%"
        Slider Name="sliZoom"
        ScrollViewer Name="scvGraph"
            Canvas Name="canGraph" Background="White"

When you adjust the slider, the following code adjusts the program’s zoom level.

// Zoom.
private double Zoom = 1;
private void sliZoom_ValueChanged(object sender,
    RoutedPropertyChangedEventArgs e)
{
    // Make sure the control's are all ready.
    if (!IsInitialized) return;

    // Display the zoom factor as a percentage.
    lblZoom.Content = sliZoom.Value + "%";

    // Get the scale factor as a fraction 0.25 - 2.00.
    double scale = (double)(sliZoom.Value / 100.0);

    // Scale the graph.
    canGraph.LayoutTransform = new ScaleTransform(scale, scale);
}

This code checks the window’s IsInitialized property to make sure that all of the controls have been created and are ready to go. It then changes the lblZoom control to display the new zoom level. It calculates a new scale factor and sets the Graph control’s LayoutTransform to scale the Graph control by the scale factor.

That makes the Graph control scale itself and all of its contents. That control is contained in a ScaleViewer, which automatically displays scroll bars if necessary so you can view the whole Graph control. (ScaleViewer is one of my favorite WPF controls.)

The only remaining part of the program is the following code, which that draws the circles and the text along them.

// Draw some circles and text.
private void Window_Loaded(object sender, RoutedEventArgs e)
{
    // Get the Canvas geometry.
    double wid = canGraph.ActualWidth;
    double hgt = canGraph.ActualHeight;
    double cx = wid / 2;
    double cy = hgt / 2;

    // Make some centered circles.
    for (int radius = 200; radius > 0; radius -= 50)
    {
        byte b = (byte)(radius / 2 + 155);
        byte r = (byte)(b / 2);
        byte g = (byte)(b / 2);

        Ellipse ellipse = new Ellipse();
        ellipse.Fill = new SolidColorBrush(
            Color.FromArgb(255, r, g, b));
        ellipse.Stroke = Brushes.Black;
        ellipse.StrokeThickness = 3;
        Canvas.SetLeft(ellipse, cx - radius);
        Canvas.SetTop(ellipse, cy - radius);
        ellipse.Width = 2 * radius;
        ellipse.Height = 2 * radius;
        canGraph.Children.Add(ellipse);
    }

    // Make some rotated text.
    double font_size = 10;
    for (int radius = 25; radius < 200; radius += 50)
    {
        const double num_angles = 6;
        double dtheta = 360 / num_angles;
        double theta = dtheta / 2;
        for (int i = 0; i < num_angles; i++)
        {
            // Convert into a counterclocckwise angle
            // where 0 is to the right.
            double angle = 90 - theta;

            // Math.Sin and Math.Cos use radians.
            double radians = (angle - 90) / 180 * Math.PI;
            double x = cx + radius * Math.Cos(radians);
            double y = cy + radius * Math.Sin(radians);

            // Use theta for the text, not angle.
            string text = ((int)theta).ToString();

            // Draw the text.
            DrawText(canGraph, text,
                new Point(x, y), angle, font_size,
                HorizontalAlignment.Center,
                VerticalAlignment.Center);

            theta += dtheta;
        }
        font_size += 3;
    }
}

The code first uses a loop to make some concentric circles. It makes them from largest to smallest so the later circles sit above the earlier ones. If you made them in smallest-to-largest order, the later circles would hide the earlier ones.

Nxet, the program uses two nested loops to draw the text. The outer loop ranges over the radii at which the program should draw text.

The inner loop ranges over the number of angles that the program needs to draw. This example draws text at six positions around the circle. The angle theta determines the position where the text should be drawn. Shortly the code will use sines and cosines to calculate the text's positions. Because Y coordinates increase downward in WPF (and Windows Forms and most programming languages), the angles used by sines and cosines increase clockwise. To make the text increase counterclockwise, the code subtracts theta from 90 to convert it into angle. It then subtracts 90 degrees and scales the result to convert angle into radians, which is the unit that the Math.Sin and Math.Cos methods require.

The code then calculates the position where the text should be drawn and calls the DrawText method to draw the text. For information on the DrawText method, see the post Draw a graph with rotated text in WPF and C#.

When the inner loop ends, the program increases the font size by 3 points so the text in the outer circles is larger.

[example]

One of the nice things about WPF is that graphics are normally represented by objects, so you can zoom in as far as you like and still get a nice, smooth result. For example, the picture on the right shows the program zoomed in so the circle is shown at 500% of its normal scale. You can see that the edges of the circles and the text 150 are still nice and smooth. Making magnified text appear smooth is harder in Windows Forms applications.

Download the example solution to see additional details and to experiment with the program. For example, you might try to scale the text so the program draws multiples of 10 between 0 and 100 instead of displaying angles in degrees.


Download Example   Follow me on Twitter   RSS feed   Donate




Posted in algorithms, graphics, mathematics | Tagged , , , , , , , , , | Leave a comment

Draw a hyperbolic spiral in C#

[spiral]

A hyperbolic spiral, which is also called an reciprocal spiral, is the inverse of an Archimedes spiral. It uses the equation r = A / θ to generate points on a spiral.

This spiral has a couple of interesting properties. First, it is drawn backwards (in some sense). Points on the Archimedes spiral and logarithmic spiral move farther from the spiral’s center as θ in increases. Points on a hyperbolic spiral move closer to the center as θ in increases.

Like a logarithmic spiral, the hyperbolic spiral doesn’t reach the spiral’s center when θ is 0. In fact, this spiral isn’t defined when θ is 0 because calculating r for that value would force you to divide by zero.

Earlier examples calculated values for r until they were larger than the distance to the farthest corner of the drawing area. We can still use that technique but with two caveats. First, in this program θ must decrease instead of increasing to produce increasingly larger values of r. Second, the program should beware of setting θ equal to 0. The example program doesn’t worry about that because r grows big enough to stop the program’s loop before that happens, but you should be aware of this issue in case you encounter it in some other program.

The earlier logarithmic spiral example calculated a maximum value for θ to make the spiral begin at (or at least very close to) the spiral’s center. This example can make a similar calculation.

This time, suppose we want generate a minimum r value of 2 so the spiral begins 2 pixels away from the center. (This spiral becomes increasingly dense as it approaches its center, so I want to leave a small hole in the middle so whole things isn’t a big blob of solid color. Setting r = 2, the spiral’s equation becomes 2 = A / &theta’. Solving for θ gives max_theta = A / 2.

The following code fragment shows how this example generates a spiral’s points.

// Return points that define a spiral.
private List<PointF> GetSpiralPoints(
    float dtheta, PointF center, float A,
    float angle_offset, float max_r)
{
    // Get the points.
    float max_theta = A / 2f;
    List<PointF> points = new List<PointF>();
    for (float theta = max_theta; ; theta -= dtheta)
    {
        // Calculate r.
        float r = A / theta;

        // Convert to Cartesian coordinates.
        float x, y;
        PolarToCartesian(r, theta + angle_offset, out x, out y);

        // Center.
        x += center.X;
        y += center.Y;

        // Create the point.
        points.Add(new PointF((float)x, (float)y));

        // If we have gone far enough, stop.
        if (r > max_r) break;
    }
    return points;
}

This method calculates max_theta as described above and makes a list to hold the spiral’s points. It then enters a loop where variable theta runs downward from max_theta. Inside the loop, the code calculates the value r, converts the result into Cartesian coordinates, and adds the point to the points list.

When r is larger than the distance to the farthest corner of the drawing area, the method breaks out of its loop and returns the spiral’s points.

Download the program to see additional details.


Download Example   Follow me on Twitter   RSS feed   Donate




Posted in algorithms, graphics, mathematics | Tagged , , , , , , , , , | Leave a comment

Review posted: “The Modern C# Challenge”

The Modern C# Challenge: Become an expert C# programmer by solving interesting programming problems

[The Modern C# Challenge]

Clock End Gooner has posted a review of my latest book, The Modern C# Challenge: Become an expert C# programmer by solving interesting programming problems. Please following this link to learn more about the book and to see the review.

Fun, Interesting, Challenging, Useful

The book contains 100 interesting programming challenges that you can use to test your C# programming skills. The problems use a wide variety of important programming techniques and many of the example solutions demonstrate key concepts such as protecting against overflow, caching data (dynamic programming), randomization, simulation, parallel processing, and more!

More info at Amazon

More info at C# Helper


Follow me on Twitter   RSS feed   Donate




Posted in books, combinatorics, cryptography, geometry, mathematics | Leave a comment

Draw a logarithmic spiral in C#

[spiral]

The post Draw an Archimedes spiral in C# uses the equation r = A˙θ to generate the points on a spiral. This example is almost exactly the same except it uses the equation to r = A˙eB˙θ to generate its points.

That equation leads to another small issue. When θ is 0, the eB˙θ becomes 1 so r = A. That means the spiral isn’t at its center point.

You can generate points closer to the center if you consider negative values for θ. The question then becomes, “How small does θ need to be?”

If we set θ small enough to make r equal to 0.1, then the resulting point will be less than one pixel away from the spiral’s center. To do that, we solve the equation 0.1 = A˙eB˙min_theta for min_theta. The result is min_theta = ln(0.1 / A) / B.

The new example is almost exactly the same as the previous example’s version. The only real change is in the GetSpiralPoints method, which uses the following code fragment to generate points on a spiral.

// Return points that define a spiral.
private List GetSpiralPoints(...)
{
    ...
    for (float theta = min_theta; ; theta += dtheta)
    {
        // Calculate r.
        float r = (float)(A * Math.Exp(B * theta));

        ...

        // If we have gone far enough, stop.
        if (r > max_r) break;
    }
    return points;
}

This code calculates min_theta as described above. It then makes variable theta loop starting from min_theta. The code uses the new formula to calculate r.

As in the previous example, the loop continues until the calculated value for r exceeds the maximum necessary value, at which point the method breaks out of its loop and returns the spiral’s points.

The rest of the example is the same as the previous one. Download the program and see the previous example for additional details.


Download Example   Follow me on Twitter   RSS feed   Donate




Posted in algorithms, graphics, mathematics | Tagged , , , , , , , , , | Leave a comment