[C# Helper]
Index Books FAQ Contact About Rod
[Essential Algorithms, Second Edition]

[The Modern C# Challenge]

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

[The C# Helper Top 100]

[Interview Puzzles Dissected]

[C# 24-Hour Trainer]

[Beginning Software Engineering]

[C# 5.0 Programmer's Reference]

[MCSD Certification Toolkit (Exam 70-483): Programming in C#]

Title: Draw a hypotrochoid (Spirograph curve) in C#

hypotrochoid hypotrochoid

The hypotrochoid is a curve drawn by rolling a circle of radius B around the inside circumference of another of radius A. A point attached to the inner circle and distance C from its center draws the curve. (See the smaller picture on the right.)

The following parametric functions generate points along the hypotrochoid.

// The parametric function X(t). private double X(double t, double A, double B, double C) { return (A - B) * Math.Cos(t) + C * Math.Cos((A - B) / B * t); } // The parametric function Y(t). private double Y(double t, double A, double B, double C) { return (A - B) * Math.Sin(t) - C * Math.Sin((A - B) / B * t); }

To trace the entire curve, the variable t must vary from 0 to 2 π B / GCD(A, B). For information on calculating the GCD (Greatest Common Divisor), see Calculate the greatest common divisor (GCD) and least common multiple (LCM) of two integers in C#.

The program uses the following code to draw the complete curve when you enter parameters and click Draw. The iter parameter determines how many points the program uses. Bigger values give smoother results, although using very small values can be interesting, too.

// Draw the hypotrochoid. private void btnDraw_Click(object sender, EventArgs e) { int A = int.Parse(txtA.Text); int B = int.Parse(txtB.Text); int C = int.Parse(txtC.Text); int iter = int.Parse(txtIter.Text); int wid = picCanvas.ClientSize.Width; int hgt = picCanvas.ClientSize.Height; Bitmap bm = new Bitmap(wid, hgt); using (Graphics gr = Graphics.FromImage(bm)) { gr.SmoothingMode = SmoothingMode.AntiAlias; int cx = wid / 2; int cy = hgt / 2; double t = 0; double dt = Math.PI / iter; double max_t = 2 * Math.PI * B / GCD(A, B); double x1 = cx + X(t, A, B, C); double y1 = cy + Y(t, A, B, C); List points = new List(); points.Add(new PointF((float)x1, (float)y1)); while (t <= max_t) { t += dt; x1 = cx + X(t, A, B, C); y1 = cy + Y(t, A, B, C); points.Add(new PointF((float)x1, (float)y1)); } // Draw the polygon. gr.DrawPolygon(Pens.Red, points.ToArray()); } picCanvas.Image = bm; }

This code parses the parameters you entered. It then makes the variable t loop from 0 to the 2 π B / GCD(A, B). For each value of t, it adds the corresponding point to a list of points. After it finishes the loop, the code draws a polygon defined by the points.

Update: Bill Wonneberger has released a WPF program based on this example. Its features include:

  • Change the drawing's foreground and background colors.
  • Saving and loading application preferences.
  • Drawing inside a WPF Viewbox so you can resize the drawing.
  • Saving the drawing in various bitmap formats.

You can download the program, see screenshots, and get more information on GitHub.

Download the example to experiment with it and to see additional details.

© 2009-2022 Rocky Mountain Computer Consulting, Inc. All rights reserved.