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. Listpoint_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.)