Draw an animated epitrochoid in C#

The example Draw an animated hypotrochoid (Spirograph curve) in C# explains how to draw an animated hypotrochoid. Every time a Timer fires, it generates the points needed to draw the curve for values t up to a certain value and then increases t to the next time it draws a bit more of the curve.

This example uses a different approach. It generates all of the points needed to draw the complete curve. Then each time the Timer fires it draws those up to a certain point. To draw the circles that generate the curve, it must also save the angles that is 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 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 = System.Drawing.Drawing2D.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,
System.Drawing.Drawing2D.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 drawing 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.)

Compare this example to:

  

 

What did you think of this article?




Trackbacks
  • No trackbacks exist for this post.
Comments
  • No comments exist for this post.
Leave a comment

Submitted comments are subject to moderation before being displayed.

 Name

 Email (will not be published)

 Website

Your comment is 0 characters limited to 3000 characters.