Animate a point on a polar coordinate curve in C#

[animate]

The example Graph a curve in polar coordinates in C# explained how to draw the flower-like curve on the right. Once you know how to draw such a curve, it’s not too hard to animate points moving along it.

The major changes this example makes to the previous one are the following.

  • This version saves the image of the curve so it can use it later to redraw the curve
  • This version saves the points on the curve so it can use them later to position the animated point
  • This version uses a Timer to periodically redraw the image with the moving point on it

The following code declares the program’s class-level variables.

// The background Bitmap.
private Bitmap Background;

// The points on the curve.
private List<PointF> Points;

// The transformation used to draw.
private Matrix Transform;

// The current point number where the atom is.
private int AtomPoint = 0;

This code declares the following variables.

  • Background – Holds an image of the curve.
  • Points – Holds the points that define the curve. The program uses them to draw the curve (as before) and to position the animated point as it moves along the curve.
  • Transform – Holds the drawing transformation matrix. The program uses it to draw the point in the correct position.
  • AtomPoint – The index in the Points list of the moving point.

The program’s Form_Load event handler is almost exactly as in the previous example. The only differences are that it enables double buffering (to make the animation smoother) and that it enables the tmrMoveAtom Timer. The following code shows the event handler with the unchanged code removed.

// Draw the graph.
private void Form1_Load(object sender, EventArgs e)
{
    // Enable double buffering.
    this.DoubleBuffered = true;

    // Make the Bitmap and associated Graphics object.
    ...

    // Enable the atom timer.
    tmrMoveAtom.Enabled = true;
}

The DrawGraph method also works almost exactly as before. The only real difference is that method uses the following code to save the drawing transformation in the class-level Transform variable.

// Set up a transformation to map the region
// -2.1 <= X <= 2.1, -2.1 <= Y <= 2.1 onto the  Bitmap.
RectangleF rect = new RectangleF(-2.1f, -2.1f, 4.2f, 4.2f);
PointF[] pts =
    {
        new PointF(0, Background.Height),
        new PointF(Background.Width, Background.Height),
        new PointF(0, 0),
    };
Transform = new Matrix(rect, pts);
gr.Transform = Transform;

The program uses this transformation later to draw the animated point so it is in the correct location on the drawing.

When the Form_Load event handler calls DrawGraph, it passes it the form-level Background Bitmap so the image is available later.

The only really new piece of code is the following event handler, which executes when the tmrMoveAtom Timer fires its Tick event (about 50 times per second).

// Draw the atom.
private void tmrMoveAtom_Tick(object sender, EventArgs e)
{
    // Refresh the image with the background.
    Bitmap bm = (Bitmap)Background.Clone();

    // Draw the atom.
    using (Graphics gr = Graphics.FromImage(bm))
    {
        gr.Transform = Transform;
        gr.SmoothingMode = SmoothingMode.AntiAlias;
        gr.FillEllipse(Brushes.Green,
            Points[AtomPoint].X - 0.075f,
            Points[AtomPoint].Y - 0.075f,
            0.15f, 0.15f);
    }

    // Display the result.
    picGraph.Image = bm;

    // Move the atom.
    AtomPoint = (AtomPoint + 1) % Points.Count;
}

This code makes a Bitmap that is a copy of the Background bitmap. This is a picture of the curve without the moving point on it. (Note that the Clone method returns an object, so the code must cast it into a Bitmap to save it in a Bitmap variable.)

The code makes a Graphics object associated with the copied Bitmap. It then sets that object’s Transform property to the class-level Transform variable. That makes this Graphics object use the same drawing transformation that was used to originally draw the curve.

The code also sets the Graphics object’s SmoothingMode property to AntiAlias so it draws smoothly.

The event handler then draws an ellipse at point number AtomPoint in the Points list and displays the result (the Background image plus the point).

The code finishes by incrementing AtomPoint so the next time the Tick event fires it draws the point in the next location. The modulus operator % makes AtomPoint start over at the first point after the program has used the last point.

Note that you can use the same technique to animate points moving along just about any curve. The basic steps are:

  • Save an image of the curve in a class-level variable
  • Save the list of points on the curve in a class-level variable
  • In a Timer component’s Tick event handler, redraw the curve’s image and draw the point on top of it
  • Increment the index of the point in the points list


Download Example   Follow me on Twitter   RSS feed   Donate




This entry was posted in algorithms, animation, graphics, mathematics and tagged , , , , , , , , , , , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *