Why you should study algorithms (plus a free book drawing)

[Essential Algorithms]

There are several reasons why you should study algorithms. I’m going to talk about four of them. (If you want to skip to the bottom, you can read about the drawing I’m having in the next few days for one of these books.)

First, it teaches you how to build specific algorithms. For example, pretty much any introductory algorithms book explains certain basic algorithms, one of which is quicksort. Quicksort is a good, general-purpose sorting algorithm that’s usually quite fast. After you learn how it works, you can use it in your programs.

But wait! Don’t many programming languages include sorting utilities? Yes they do. In fact, many of them use quicksort, at least under some circumstances. The reason they don’t use quicksort all of the time is that other algorithms are sometimes faster. For example, the countingsort can be much faster if the values being sorted are integers that span a relatively small range. For example, countingsort would work quite well if you need to sort 1 million integer values between 1 and 10,000. For another example, bubblesort is very fast for sorting small lists. For example, it is often faster than quicksort or countingsort if you only need to sort 5 items.

That brings me to the second reason why you should study algorithms: so you know which algorithm to use under different circumstances. Studying algorithms lets you know what kinds of algorithms are possible and which might be best suited for a particular problem. The .NET Framework includes sorting tools, but you may be able to sort much more quickly if you have special information about the data that you are sorting. A good background in algorithms will let you know what other kinds of algorithms are out there for building trees, searching databases, finding paths through networks, solving optimization problems, fitting curves to points, and many other useful tasks.

The third reason for studying algorithms, and the one that is probably the most important, it that it gives your brain a workout. Professional football players spend plenty of time in the gym even though they will rarely need to perform bench presses during a game. Similarly, working with a variety of algorithms exercises your brain. It teaches you new techniques for solving problems. It also teaches you problem-solving approaches that you may help you find solutions to completely unrelated problems. It’s practice for solving the problems that you will actually face on the mean streets of programming.

(This is also the main reason why you learn algebra in school. It’s not that your teachers think everyone will use algebra or calculus in their daily lives. They’re trying to make youi smarter.)

The final reason for studying algorithms (at least the final reason that I’m going to talk about now) is that they’re fun! Figuring out how to implement a tricky algorithm is sort of like solving a jigsaw or Sudoku puzzle. It’s a great feeling when all of the pieces fit together to give you something whole. Unlike Sudoko, however, when you’re done implementing an algorithm, you have something useful. It’s also an amazing feeling to dump a bunch of data into a 3D graphics program and have a colorful fractal or photo-realistic picture pop out!

Over the years I have written many books that are largely workouts for your brain. Those include algorithms books, 2- and 3-dimensional graphics books, miscellaneous interesting topics books, and even a book about interview puzzles. (Even my database design book will probably make you think.) Here are my latest titles that fit this category.

[The Modern C# Challenge]

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

This book includes 100 problems (with solutions) that you can use to test and hone your C# programming skills. They cover an eclectic assortment of topics, such as mathematical calculations, geometry, dates and times, the filesystem, simulations, and cryptography. These problems won’t make you an expert in those fields, but they will give you some experience with a wide variety of useful topics.


[WPF 3d]

WPF 3d, Three-Dimensional Graphics with WPF and C#

This easy-to-read guide provides everything you need to know to get started writing striking 3D graphics programs with WPF and C#. The book’s three parts describe 3D basics, building many different shapes, and advanced topics. More than 100 example programs covering such topics as:

  • The lights, cameras, materials, texture coordinates, and other details that you need to create a 3D scene
  • Orthographic, perspective, and other projections that emphasize different aspects of a scene
  • Special material treatments such as specular reflection, wireframes, and solid and translucent materials
  • Examples of many shapes including flat polygons, boxes, Platonic solids, spheres, tori, cones, and more
  • Advanced objects such as parametric surfaces, surfaces of transformation, fractal surfaces, and 2D and 3D text
  • Higher-level scene management to let users select and move objects
  • Advanced techniques such as loading models created in other applications and using skeletons

    [Interview Puzzles Dissected]

    Interview Puzzles Dissected, Solving and Understanding Interview Puzzles

    Job Candidates, Interviewers, and Puzzle Enthusiasts

    Whether you’re applying for a programming job or a position on Wall Street, interview puzzles are the norm at many high-tech companies. This book explains how to solve more than 200 of the hardest and most common interview puzzles in use. Interview Puzzles Dissected:

    • Shows how to solve more than 200 challenging interview puzzles
    • Reveals underlying techniques that let you solve problems that you haven’t seen before
    • Tells how you can show the interviewer that you can think in an organized fashion
    • Explains how to get “partial credit” when all else fails and you just can’t solve a puzzle
    • Includes programming challenges to give you a deeper understanding of puzzles (obviously only if you’re a programmer)

    [Essential Algorithms]


    Essential Algorithms, A Practical Approach to Computer Algorithms

    A friendly and accessible introduction to the most useful algorithms.

    Computer algorithms are the basic recipes for programming. Professional programmers need to know how to use algorithms to solve difficult programming problems. Written in simple, intuitive English, this book describes how and when to use the most practical classic algorithms, and even how to create new algorithms to meet future needs. The book also includes a collection of questions that can help readers prepare for a programming job interview.


    Drawing

    I’m holding a drawing to give away 10 free copies of my book The Modern C# Challenge. To enter, simply send your name and email address to me at RodStephens@CSharpHelper.com. Use the subject line “The Modern C# Challenge book drawing” so I know what your email is about. All I ask in return is that you post a review. The deadline is January 18, 2019, so act now!

    For a little more information, look at this post.


    Follow me on Twitter   RSS feed   Donate




Posted in 3D graphics, algorithms, books, graphics | Tagged , , , , , , , , , | Leave a comment

Book Drawing: The Modern C# Challenge

I’m holding a drawing for 10 copies of my latest book, The Modern C# Challenge. Here’s the short blurb about this book.


The Modern C# Challenge

Become an expert C# programmer by solving interesting programming problems

[The Modern C# Challenge]

This book includes 100 problems (with solutions) that you can use to test and hone your C# programming skills. They cover an eclectic assortment of topics, such as mathematical calculations, geometry, dates and times, the file system, simulations, and cryptography. These problems won’t make you an expert in those fields, but they will give you some experience with a wide variety of useful topics.

To enter the drawing, simply send your name and email address to me at RodStephens@CSharpHelper.com. Use the subject line “The Modern C# Challenge book drawing” so I know what your email is about. All I ask in return is that you post a review.

From previous experience I know that not all that many people enter this sort of drawing, so your chances of winning may be fairly good.

The deadline is January 18, 2019. I’ll announce the winners (without your email addresses) shortly after that. The book will be delivered as an eBook.

Goood luck!


Follow me on Twitter   RSS feed   Donate




Posted in algorithms, books | Tagged , , , , , , , , | 1 Comment

Save and restore lines drawn by a WPF line editor in C#

[WPF line editor]

The example Make a WPF line editor C# shows how to make a program that lets the user draw lines on a WPF canvas. This example is similar but it also allows you to save and restore drawings.

The WPF objects that represent lines are from the Line class. Unfortunately that class is marked as serializable. If you want to save and restore the lines in a serialization, you need to make your own class that is serializable. This example uses the following Segment class.

// Represent a serializable line segment.
[Serializable()]
public class Segment
{
    public double X1, Y1, X2, Y2;
    public Segment()
    {
    }
    public Segment(double x1, double y1, double x2, double y2)
    {
        X1 = x1;
        Y1 = y1;
        X2 = x2;
        Y2 = y2;
    }
}

This class stores the coordinates needed by a WPF line. You can add other properties such as line thickness and color if you like.

This class has three key features. First, it is marked with the Serializable attribute. Second, it must be public. Third, it must have a constructor that takes no parameters. It includes another constructor to make working with the class easier.

The following code shows how the WPF line editor saves the current lines into an XML file.

// Save a serialized file.
private void Save_Click(object sender, RoutedEventArgs e)
{
    // Get the name of the file where we should save the segments.
    SaveFileDialog dlg = new SaveFileDialog();
    dlg.DefaultExt = ".xml";
    dlg.Filter = "XML (*.xml)|*.xml|All Files (*.*)|*.*";
    Nullable<bool> result = dlg.ShowDialog();
    if (result.Value != true) return;

    // Make a list of segments.
    List<Segment> segments = new List<Segment>();
    foreach (object obj in canDrawing.Children)
    {
        if (obj is Line)
        {
            Line line = (Line)obj;
            segments.Add(new Segment(line.X1, line.Y1, line.X2, line.Y2));
        }
    }

    // Make the XmlSerializer.
    XmlSerializer serializer =
        new XmlSerializer(typeof(List<Segment>));
    using (FileStream stream = File.Create(dlg.FileName))
    {
        serializer.Serialize(stream, segments);
    }
}

This method creates a SaveFileDialog and uses it to let the user pick teh file where the drawing should be saved.

Next, it creates a list of Segment objects named segments. It then loops through the Canvas control’s children. If a child is a Line object, the code converts the generic child object into a Line and adds it to the segments list.

The method then creates an XML serializer that can serialize objects of the type List<Segment>. It creates a file stream to create the file selected by the OpenFileDialog and uses the serializer to serialize the segments list into the file.

In order to load a serialized file, the program uses the following simple helper routine.

private void ClearCanvas()
{
    // Remove existing segments.
    for (int i = canDrawing.Children.Count - 1; i >= 0; i--)
    {
        if (canDrawing.Children[i] is Line)
            canDrawing.Children.RemoveAt(i);
    }
}

This method simply loops through the Canvas control’s children and removes those that are Line objects.

The following code shows how the program restores a previously saved drawing.

// Open a serialized file.
private void Open_Click(object sender, RoutedEventArgs e)
{
    // Get the name of the file where we should save the segments.
    OpenFileDialog dlg = new OpenFileDialog();
    dlg.DefaultExt = ".xml";
    dlg.Filter = "XML (*.xml)|*.xml|All Files (*.*)|*.*";
    Nullable<bool> result = dlg.ShowDialog();
    if (result.Value != true) return;

    // Remove existing segments.
    ClearCanvas();

    // Make the XmlSerializer.
    XmlSerializer serializer =
        new XmlSerializer(typeof(List<Segment>));
    using (FileStream stream = 
        File.Open(dlg.FileName, FileMode.Open))
    {
        List<Segment> segments =
            (List<Segment>)serializer.Deserialize(stream);

        // Add the loaded segments.
        foreach (Segment segment in segments)
        {
            Line new_line = new Line();
            new_line.X1 = segment.X1;
            new_line.Y1 = segment.Y1;
            new_line.X2 = segment.X2;
            new_line.Y2 = segment.Y2;
            new_line.Stroke = Brushes.Black;
            canDrawing.Children.Add(new_line);
        }
    }
}

This method uses an OpenFileDialog to let the user select the XML file to open. If the user selects a file, the code calls the ClearCanvas method to remove any existing lines. It then creates a serializer that can serialize the List<Segment> type.

Next, the method creates a file stream to read the selected file and uses the serializer to deserialize the file and create a List<Segment> from its contents.

Finally, the method loops through the returned Segment objects and uses them to add new Line objects to the program’s Canvas control.

That’s all of the code that deals with saving and restoring drawings in the WPF line editor. To see additional details, download the example program and see the previous post Make a WPF line editor C#.


Download Example   Follow me on Twitter   RSS feed   Donate




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

Convert camel case into underscore case in C#

[underscore case]

Lately I’ve been doing a lot of C#-to-python conversion. The style in C# is to use camel case where you capitalize the first letter each each word after the first one in a variable’s name as in thisIsAVariableName. The style in Python is underscore case where you separate the words in a name with underscores as in this_is_a_variable_name. Several studies have shown that underscore case is easier to read than camel case, but that’s not the style in C# and some other languages.

Anyway, I wrote this program to make it slightly easier to convert from camel case to underscore case. If you enter the camel cased text in the upper text box and click Convert, the following surprisingly short code executes.

// Convert from TitleCase to underscore_case.
private void btnConvert_Click(object sender, EventArgs e)
{
    StringBuilder sb = new StringBuilder();
    bool to_upper = chkUpperCase.Checked;
    bool start_of_word = true;
    foreach (char ch in txtTitleCase.Text)
    {
        if (char.IsUpper(ch))
            if (!start_of_word) sb.Append("_");

        if (to_upper)
            sb.Append(ch.ToString().ToUpper());
        else
            sb.Append(ch.ToString().ToLower());

        start_of_word = char.IsWhiteSpace(ch);
    }
    txtUnderscoreCase.Text = sb.ToString();
}

This code creates a StringBuilder, gets the input text, and sets start_of_word to true to indicate that the next letter will start a word. If then loops through the entered text letter-by-letter.

If a letter is in upper case, the code adds an underscore to the StringBuilder if this is not the start of a new word. That allows the code to convert either camelCase or PascalCase to underscore_case.

The code then adds the input character to the StringBuilder, converting the character to upper case if the Upper Case checkbox is checked. The code then sets start_of_word to true if the character was whitespace to indicate that the next non-whitespace character will start a new word.

After it has finished processing all of the input characters, the code returns the result.


Download Example   Follow me on Twitter   RSS feed   Donate




Posted in programs, strings | Tagged , , , , , , , , | 2 Comments

Create sized oval images in C#

[oval images]

Almost as soon as I had finished the example Create oval images in C#, I realized that it wouldn’t work for my purposes. I wanted to make oval images for several people. Unfortunately, that program didn’t let you make images of the same size, so I created this program.

Instead of having you select an oval by clicking and dragging, this version lets you enter the oval’s width and height. You can then drag the oval into position to select part of the picture.

The following code shows the parts of the program that deal with moving the oval.

private Rectangle OvalRect =
    new Rectangle(0, 0, 200, 250);

// Select an elliptical area.
private bool Dragging = false;
private Point MousePos;
private void picImage_MouseDown(object sender, MouseEventArgs e)
{
    Dragging = true;
    MousePos = e.Location;
}

private void picImage_MouseMove(object sender, MouseEventArgs e)
{
    if (!Dragging) return;
    OvalRect.X += e.Location.X - MousePos.X;
    OvalRect.Y += e.Location.Y - MousePos.Y;
    MousePos = e.Location;

    DrawImage();
}

private void picImage_MouseUp(object sender, MouseEventArgs e)
{
    Dragging = false;
}

The variable OvalRect holds the oval’s location.

The MouseDown event handler sets Dragging to true so the program remembers that a drag is in progress. It then saves the mouse’s current position in variable MousePos.

Teh MouseMove event handler first checks Dragging to see if a drag is in progess and returns if one is not. It then calculates the distance that the mouse has moved since the last time its position was recorded and moves OvalRect by that amount. It finishes by calling DrawImage to draw the original image with the oval on it.

The MouseUp event handler simply sets Dragging to false to indicate that the drag is no longer in progress.

The following code shows how the DrawImage method draws the image with the oval.

private void DrawImage()
{
    Bitmap bm = new Bitmap(OriginalImage);
    using (Graphics gr = Graphics.FromImage(bm))
    {
        gr.SmoothingMode = SmoothingMode.AntiAlias;
        gr.DrawEllipse(Pens.Magenta, OvalRect);
    }
    picImage.Image = bm;
}

[oval images]

This method creates a new Bitmap that is a copy of the original image as loaded from a file. It then creates an associated Graphics object and sets its SmoothingMode property so it can draw a smooth oval. The code then calls the Graphics object’s DrawEllipse method to draw the ellipse at its current position. It finishes by displaying the image in the picImage PictureBox.

The rest of the example is the same as the previous post. Visit that example and download this one to see additional details.


Download Example   Follow me on Twitter   RSS feed   Donate



Posted in drawing, image processing | Tagged , , , , , , , , , , , | Leave a comment

Use WPF 3d techniques to draw a snowman with WPF and C#


[WPF 3d]

This example shows how to use the tools and techniques described in my book WPF 3d, Three-Dimensional Graphics with WPF and C# to draw a three-dimensional snowman. I won’t go into all of the details because there are a whole book’s worth, but here’s the code that builds the snowman model.

// Define the model.
private void DefineModel()
{
    // Show the axes.
    // MeshExtensions.AddAxes(MainGroup);

    // Make the snowman's body.
    const double bodyR = 2;
    const double headR = 1.25;
    MeshGeometry3D bodyMesh = new MeshGeometry3D();
    double headY = 0.8 * (headR + bodyR) - 1;
    MeshExtensions.AddSphere(bodyMesh,
        new Point3D(0, headY, 0),
        headR, 40, 20, true);
    MeshExtensions.AddSphere(bodyMesh,
        new Point3D(0, -1, 0),
        bodyR, 40, 20, true);
    MainGroup.Children.Add(bodyMesh.MakeModel(Brushes.White));

    // Nose.
    const double noseR = 0.2;
    MeshGeometry3D noseMesh = new MeshGeometry3D();
    MeshExtensions.AddSphere(noseMesh,
        new Point3D(0, headY, 0),
        noseR, 20, 10, true);
    MainGroup.Children.Add(noseMesh.MakeModel(Brushes.Orange));
    noseMesh.ApplyTransformation(new ScaleTransform3D(1, 1, 3));
    noseMesh.ApplyTransformation(new TranslateTransform3D(0, 0, headR));

    // Eyes.
    const double eyeR = 0.15;
    MeshGeometry3D eyeMesh = new MeshGeometry3D();
    MeshExtensions.AddSphere(eyeMesh,
        new Point3D(0.4, 0.4, -0.15),
        eyeR, 7, 3, false);
    MeshExtensions.AddSphere(eyeMesh,
        new Point3D(-0.4, 0.4, -0.15),
        eyeR, 6, 3, false);
    MainGroup.Children.Add(eyeMesh.MakeModel(Brushes.Black));
    eyeMesh.ApplyTransformation(
        new TranslateTransform3D(0, headY, headR));

    // Buttons.
    const double buttonR = 0.17;
    MeshGeometry3D button1Mesh = new MeshGeometry3D();
    MeshExtensions.AddSphere(button1Mesh,
        new Point3D(0, 0, bodyR),
        buttonR, 7, 3, false);
    button1Mesh.ApplyTransformation(new TranslateTransform3D(0, -1, 0));
    MainGroup.Children.Add(button1Mesh.MakeModel(Brushes.DarkBlue));

    MeshGeometry3D button2Mesh = new MeshGeometry3D();
    MeshExtensions.AddSphere(button2Mesh,
        new Point3D(0, 0, bodyR),
        buttonR, 6, 3, false);
    Rotation3D rotation2 =
        new AxisAngleRotation3D(new Vector3D(1, 0, 0), -23);
    button2Mesh.ApplyTransformation(
        new RotateTransform3D(rotation2, new Point3D()));
    button2Mesh.ApplyTransformation(new TranslateTransform3D(0, -1, 0));
    MainGroup.Children.Add(button2Mesh.MakeModel(Brushes.DarkBlue));

    MeshGeometry3D button3Mesh = new MeshGeometry3D();
    MeshExtensions.AddSphere(button3Mesh,
        new Point3D(0, 0, bodyR),
        buttonR, 7, 3, false);
    Rotation3D rotation3 =
        new AxisAngleRotation3D(new Vector3D(1, 0, 0), -46);
    button3Mesh.ApplyTransformation(
        new RotateTransform3D(rotation3, new Point3D()));
    button3Mesh.ApplyTransformation(new TranslateTransform3D(0, -1, 0));
    MainGroup.Children.Add(button3Mesh.MakeModel(Brushes.DarkBlue));

    // Hat.
    MeshGeometry3D hatMesh = new MeshGeometry3D();
    const double hatR = 0.8;
    const double hatL = 1.65;
    Point3D[] polygon = G3.MakePolygonPoints(20, new Point3D(),
        new Vector3D(hatR, 0, 0), new Vector3D(0, 0, hatR));
    MeshExtensions.AddConeFrustum(hatMesh, new Point3D(0, headY, 0),
        polygon, new Vector3D(0, -3 * hatL, 0), hatL);

    // Brim.
    const double brimR = 1.5 * hatR;
    Point3D[] brimPolygon = G3.MakePolygonPoints(20,
        new Point3D(0, -hatL / 2, 0),
        new Vector3D(brimR, 0, 0), new Vector3D(0, 0, brimR));
    MeshExtensions.AddCylinder(hatMesh, brimPolygon,
        new Vector3D(0, -0.2, 0), true);

    Rotation3D hatRotation =
        new AxisAngleRotation3D(new Vector3D(0, 0, 1), -10);
    hatMesh.ApplyTransformation(
        new RotateTransform3D(hatRotation, new Point3D()));
    hatMesh.ApplyTransformation(new TranslateTransform3D(0.5, headY + 2, 0));
    MainGroup.Children.Add(hatMesh.MakeModel(Brushes.Green));
}

The basic steps for creating a WPF 3d object are:

  1. Create a mesh to hold a shape’s geometry.
  2. Use methods defined by the MeshExtensions and G3 classes to create objects such as spheres, cubes, boxes, polygons, tori, frustums, parametric surfaces, and other shapes and add them to the mesh.
  3. Transform the mesh if desired to translate, rotate, or scale the objects.
  4. Add the mesh to the main object group specifying the color that you want to give the mesh.

This example uses those techniques to create the snowman’s two body parts, nose, eyes, buttons, and hat.


[WPF 3d]

My book WPF 3d includes many other options for working with 3D scenes. For example, it lets you determine whether objects are smoothed. This example makes the snowman’s body, nose, and hat smooth, but it makes its eyes and buttons not smooth (so they look a little bit more like coal).

Other techniques described in the book include:

  • The lights, cameras, materials, texture coordinates, and other details that you need to create a 3D scene
  • Orthographic, perspective, and other projections that emphasize different aspects of a scene
  • Special material treatments such as specular reflection, wireframes, and solid and translucent materials
  • Examples of many shapes including flat polygons, boxes, Platonic solids, spheres, tori, cones, and more
  • Advanced objects such as parametric surfaces, surfaces of transformation, fractal surfaces, and 2D and 3D text
  • Higher-level scene management to let users select and move objects
  • Advanced techniques such as loading models created in other applications and using skeletons
      Visit the WPF 3d web page to see sample pictures and more details.


      Download Example   Follow me on Twitter   RSS feed   Donate




Posted in 3D, 3D graphics, books, drawing, graphics, XAML | Tagged , , , , , | Leave a comment

Pingback: Code Project post “Clipping Plane in WPF 3D”

[WPF 3D]

The Code Project post Clipping Plane in WPF 3D by charles922 references a couple of my WPF 3D posts. His post explains several WPF 3D concepts including;

[WPF 3D]

To see Charles’ post, click here.

For LOTS more information on three-dimensional graphics in WPF, see my book WPF 3d,
Three-Dimensional Graphics with WPF and C#
.


Follow me on Twitter   RSS feed   Donate



Posted in 3D, 3D graphics, graphics | Tagged , , , , , , , , , , , , , , | Leave a comment

Create oval images in C#

[oval images]

This example lets you create oval images with transparent backgrounds. It includes some features such as menus that let you load and save files. Download the example to see those details. The more interesting part is the code that creates the oval images. The process starts when you press the mouse down over the image and the following MouseDown event handler executes.

// Select an elliptical area.
private bool Drawing = false;
private Point StartPoint, EndPoint;
private void picImage_MouseDown(object sender, MouseEventArgs e)
{
    Drawing = true;
    StartPoint = e.Location;
    EndPoint = e.Location;
}

The Drawing variable is true while you are in the process of selecting an oval area. The StartPoint and EndPoint variables record the corners of the area that you are selecting.

The MouseDown event handler sets Drawing to true and saves the mouse’s current location.

When you move the mouse, the following event handler executes.

private void picImage_MouseMove(object sender, MouseEventArgs e)
{
    if (!Drawing) return;
    EndPoint = e.Location;
    DrawImage();
}

If Drawing is false, then you are not selecting an area so the method simply returns. Otherwise the method saves the mouse’s new location in EndPoint and calls DrawImage (described shortly) to display the selected area.

When you release the mouse, the following event handler executes.

private void picImage_MouseUp(object sender, MouseEventArgs e)
{
    Drawing = false;
}

This simply sets Drawing to false to end the current selection.

The following code shows the DrawImage method.

private void DrawImage()
{
    Bitmap bm = new Bitmap(OriginalImage);
    using (Graphics gr = Graphics.FromImage(bm))
    {
        gr.SmoothingMode = SmoothingMode.AntiAlias;
        gr.DrawEllipse(Pens.Magenta,
            SelectedRect(StartPoint, EndPoint));
    }
    picImage.Image = bm;
}

This code creates a new bitmap named bm that is a copy of the image stored in OriginalImage. (When you load an image, the program saves a copy of it in OriginalImage.) It then creates an associated Graphics object, sets its SmoothingMode property to produce smooth curves, and draws an ellipse showing the area that you have selected. Finally, the code draws a magenta oval around the selected area and makes the PictureBox display the result.

When you save results, the program uses the following method to create oval images.

private Bitmap MakeOvalImage(Point start_point, Point end_point)
{
    Rectangle rect =
        SelectedRect(start_point, end_point);
    Bitmap bm = new Bitmap(rect.Width, rect.Height);

    using (Graphics gr = Graphics.FromImage(bm))
    {
        gr.SmoothingMode = SmoothingMode.AntiAlias;
        gr.Clear(Color.Transparent);
        using (TextureBrush brush =
            new TextureBrush(OriginalImage, rect))
        {
            rect.X = 0;
            rect.Y = 0;
            gr.FillEllipse(brush, rect);
        }
    }
    return bm;
}

This method creates a rectangle representing the area that you selected. It then makes a bitmap that has a size to match the size of the area that you selected. It creates an associated Graphics object and sets SmoothingMode to draw smooth curves. The code then clears the new bitmap with the color Transparent to give it a transparent background.

[oval images]

Now comes the tricky part. The code creates a new TextureBrush using the images as its texture. The second parameter to the constructor makes the brush use only the selected part of the picture as its brush. Now if you use the brush to fill a shape, it will fill the shape with copies of the selected part of the picture. The code then simply fills an ellipse with the brush. Note that this rectangle has the size of the area that you selected but has upper left corner at (0, 0). That makes the oval fill the new bitmap.

The only remaining trick to saving oval images is to be sure to save the image in .PNG format. If you save the image in .JPG format or some other lossy format, the file won’t preserve the image’s transparent background. The program uses the SaveImage method described in the post Save images with an appropriate format depending on the file name’s extension in C# to save the image in a format that matches the file extension that you use. See that post for details.

Download the example program for additional details.


Download Example   Follow me on Twitter   RSS feed   Donate




Posted in drawing, image processing | Tagged , , , , , , , , , , | 1 Comment

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