Draw an animated epitrochoid in C#

animated epitrochoid

This example shows one way to draw an animated epitrochoid. (See the example Draw an epitrochoid in C# for an explanation of how to draw an epitrochoid.) This program generates all of the points needed to draw the complete curve. Then each time its Timer fires, it draws the points up to a certain position in the list of points. To draw the circles that generate the curve, it also saves the angles that are used to generate the points.

The program uses the following code to save the points and angles.

// The curve's points.
private PointF[] Points = null;
private float[] Thetas = null;
...
// Make the curve's points.
private void MakeEpitrochoidPoints(
    float a, float b, float h, float dt)
{
    // Calculate the stop value for t.
    float stop_t = (float)(b * 2 * Math.PI);

    // Find the points.
    List point_list = new List();
    List theta_list = new List();

    point_list.Add(new PointF(X(a, b, h, 0), Y(a, b, h, 0)));
    theta_list.Add(0);
    for (float t = dt; t <= stop_t; t += dt)
    {
        point_list.Add(new PointF(X(a, b, h, t), Y(a, b, h, t)));
        theta_list.Add(t);
    }
    point_list.Add(new PointF(X(a, b, h, 0), Y(a, b, h, 0)));
    theta_list.Add(0);

    Points = point_list.ToArray();
    Thetas = theta_list.ToArray();
}

// The parametric function X(t).
private float X(float a, float b, float h, float t)
{
    return (float)((a + b) * Math.Cos(t) -
        h * Math.Cos(t * (a + b) / b));
}

// The parametric function Y(t).
private float Y(float a, float b, float h, float t)
{
    return (float)((a + b) * Math.Sin(t) -
        h * Math.Sin(t * (a + b) / b));
}

The MakeEpitrochoidPoints method calculates the values for the angle that it must traverse to draw the whole curve. It then loops through those values saving the curve's points and the angles in the lists. It finishes by converting the lists into arrays.

The X and Y methods are the parametric functions that generate the curve.

The following code shows how the program draws the curve.

// Draw another point.
private void tmrDraw_Tick(object sender, EventArgs e)
{
    MaxPointToDraw++;
    if (MaxPointToDraw >= Points.Length - 1)
    {
        tmrDraw.Enabled = false;
        Cursor = Cursors.Default;
    }
    picCanvas.Refresh();
}

// Draw the epitrochoid.
private void picCanvas_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.Clear(picCanvas.BackColor);
    if (Points == null) return;

    e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;

    // Scale and center.
    float scale = Math.Min(
        picCanvas.ClientSize.Width * 0.45f,
        picCanvas.ClientSize.Height * 0.45f);
    e.Graphics.ScaleTransform(
        scale / (a + b + h), scale / (a + b + h));
    e.Graphics.TranslateTransform(
        picCanvas.ClientSize.Width / 2,
        picCanvas.ClientSize.Height / 2,
        MatrixOrder.Append);

    // Draw the circles.
    using (Pen black_pen = new Pen(Color.Black, 0))
    {
        // Inner circle.
        e.Graphics.DrawEllipse(black_pen, -a, -a, 2 * a, 2 * a);

        // Outer circle.
        float theta = Thetas[MaxPointToDraw];
        float cx = (float)((a + b) * Math.Cos(theta));
        float cy = (float)((a + b) * Math.Sin(theta));

        e.Graphics.DrawEllipse(black_pen,
            cx - b, cy - b, 2 * b, 2 * b);

        // The line segment.
        e.Graphics.DrawLine(black_pen, cx, cy,
            Points[MaxPointToDraw].X, Points[MaxPointToDraw].Y);
    }

    // Draw the curve.
    using (Pen white_pen = new Pen(Color.White, 0))
    {
        for (int i = 0; i < MaxPointToDraw; i++)
        {
            e.Graphics.DrawLine(white_pen,
                Points[i], Points[i + 1]);
        }
    }
}

When the Timer fires, it increments MaxPointToDraw to draw another point and then refreshes the picCanvas PictureBox.

The picCanvas Paint event handler draws the circles and line segment that generate the curve. It then loops through the correct number of points that make up the curve. (This would be easier if the DrawLines method took a parameter indicating the number of lines to draw from the array instead of just drawing them all, but admittedly this is a fairly unusual application.)


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 *