Home > Guides > Programming > .NET and Windows Programming

Toggle Open Guide Table of ContentsGuide Contents

Close Table of ContentsGuide Contents

Close Table of Contents

Drawing Cycloid Curves

Last updated Sep 23, 2005.

One of my favorite childhood toys was the Spirograph. I spent hours experimenting with different wheels and colored pens, creating all manner of intricate designs.

The physical toy doesn't appear to be available anymore, except perhaps on the used market. I guess kids these days aren't interested in a toy if it doesn't have flashing lights and sound effects. That's too bad, really, but I'll refrain from the social commentary.

In its simplest form, the Spirograph toy consists of two plastic wheels that have interlocking teeth like gears. One of the gears is pinned to a drawing surface (usually a piece of paper placed on top of a piece of cardboard). The other gear has a number of holes in it that are large enough for a ballpoint pen tip. The user places the teeth of the floating gear into the teeth of the fixed gear, sticks the pen through one of the holes, and begins moving the floating gear around the fixed gear. The pen traces a path on the paper. The result is similar to Figure 47.

Figure 47

Figure 47: A design created by the Spirograph toy

Although it seemed magical to me as a child, there's really nothing magic about the Spirograph. It's just an example of a trochoid curve (a modified cycloid curve), something we can simulate on the computer fairly easily.

Simple Cycloid Curves

The simplest cycloid curve is drawn by tracing the path of a point at the edge of a circle as the circle rolls in a straight line. The MathWorld article linked above contains an animated Java applet that draws such a cycloid curve. I'll leave the animation for another time and focus first on drawing the curve.

The parametric equations for drawing a cycloid curve are given in the MathWorld article as:

x = a(t - sin t)

y = a(1 - cos t)

Where a is the radius of the circle and t is the rotation angle (in radians) of the point on the circle as it rolls along the line. These equations assume that the curve starts at the origin (position (0, 0)), so you have to add the actual starting coordinates to the computed values. Code below shows how to use these equations in drawing a cycloid curve.

[C#]

private void button1_Click(object sender, System.EventArgs e)
{
  // Constants control the position and size of the circle
  // and the number of points to plot on the curve.
  const int baseLine = 200;
  const Double radius = 40;
  const int PointsPerCurve = 100;

  Graphics g = CreateGraphics();
  try
  {
    // Clear the drawing canvas
    g.Clear(this.BackColor);

    // Draw the base line
    g.DrawLine(Pens.Black, 0, (float)baseLine, this.ClientRectangle.Right, (float)baseLine);

    // Compute the starting point 
    PointF ptStart = new PointF((float)radius, (float)baseLine);

    // Draw the curve
    ptStart = DrawCycloid(g, ptStart, radius, PointsPerCurve);
    
    // Draw it again starting at the previous end point
    DrawCycloid(g, ptStart, radius, PointsPerCurve);
  }
  finally
  {
    g.Dispose();
  }
}

PointF DrawCycloid(Graphics g, PointF ptStart, double radius, int PointsPerCurve)
{
  // There are always 2*PI radians in a circle
  const Double radiansPerCircle = 2 * Math.PI;
  Double angleStep = radiansPerCircle / PointsPerCurve;  // angle step, in radians
  PointF oldPoint = ptStart;
  Double angle = 0;
  for (int pt = 0; pt < PointsPerCurve; pt++)
  {
    angle += angleStep;
    // x = a(t-sin t)
    // y = a(1-cos t)
    // Point is traslated from the starting point.
    PointF newPoint = new PointF(
      ptStart.X + (float)(radius * (angle - Math.Sin(angle))),
      ptStart.Y - (float)(radius * (1 - Math.Cos(angle))));

    // Draw the curve segment
    g.DrawLine(Pens.Red, oldPoint, newPoint);

    // and setup for the next go 'round
    oldPoint = newPoint;
  }

  // return the ending point
  return oldPoint;
}

[Visual Basic]

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
  ' Constants control the position and size of the circle
  ' and the number of points to plot on the curve.
  Const baseLine As Integer = 200
  Const radius As Double = 40
  Const PointsPerCurve As Integer = 100

  Dim g As Graphics = CreateGraphics()
  Try
    ' Clear the drawing canvas
    g.Clear(Me.BackColor)

    ' Draw the base line
    g.DrawLine(Pens.Black, 0, baseLine, Me.ClientRectangle.Right, baseLine)

    ' Compute the starting point 
    Dim ptStart As New PointF(radius, baseLine)

    ' Draw the curve
    ptStart = DrawCycloid(g, ptStart, radius, PointsPerCurve)

    ' Draw it again starting at the previous end point
    DrawCycloid(g, ptStart, radius, PointsPerCurve)
  Finally
    g.Dispose()
  End Try

End Sub

Private Function DrawCycloid(ByVal g As Graphics, ByVal ptStart As PointF, ByVal radius As Double, ByVal PointsPerCurve As Integer) As PointF
  ' There are always 2*PI radians in a circle
  Const radiansPerCircle As Double = 2 * Math.PI
  Dim angleStep As Double = radiansPerCircle / PointsPerCurve ' angle step, in radians
  Dim oldPoint As PointF = ptStart
  Dim angle As Double = 0
  Dim pt As Integer
  For pt = 1 To PointsPerCurve
    angle = angle + angleStep
    ' x = a(t-sin t)
    ' y = a(1-cos t)
    ' Point is traslated from the starting point.
    Dim newPoint As New PointF( _
     ptStart.X + (radius * (angle - Math.Sin(angle))), _
     ptStart.Y - (radius * (1 - Math.Cos(angle))))

    'Draw the curve segment
    g.DrawLine(Pens.Red, oldPoint, newPoint)

    ' and setup for the next go 'round
    oldPoint = newPoint
  Next

  ' return the ending point
  Return oldPoint
End Function

This code is intended to be used in a Windows Forms application. The first method, <tt>button1_Click</tt>, sets up for drawing the curve. It allocates the <tt>Graphics</tt> object that will be drawn on, draws the base line, and then calls the <tt>DrawCycloid</tt> method to draw the actual cycloid curve.

The button click handler defines constants that determine the size of the circle and the number of line segments used to draw the curve. The number of line segments used determines the smoothness of the curve. More on that below.

The <tt>DrawCycloid</tt> method uses the parametric equations to compute the points on the curve and draw the line segments. It uses passed <tt>PointsPerCurve</tt> value to compute the angle step size. Figure 48 shows the curve as drawn by my sample program.

Figure 48

Figure 48 - The curve drawn by the example code

One thing you can do with the computer simulation that you can't easily do with a physical toy is adjust the number of line segments used to create the curve. The curve shown in Figure 48 was drawn by plotting 100 different points and drawing line segments between them. This results in a smooth curve for even much larger circles. Interesting things happen, though, if you drastically decrease the number of points on the curve. For example, if you change the <tt>PointsPerCurve<tt> value to 5, you end up with the "curve" shown in Figure 49.

Figure 49

Figure 49 - Decreasing the number of points on the curve

When you significantly reduce the number of line segments used to draw the curve, you can see the individual segments. The illusion of a smooth curve is destroyed. This doesn't look terribly exciting when drawing the curves on a straight line, but can create some interesting effects when you begin to draw the curves around a circle. We'll come back to that in a later section.

Discussions

Copies of the array?
Posted Dec 23, 2008 03:40 PM by luige21
1 Replies
Hi
Posted Dec 5, 2008 05:10 AM by ajay2000bhushan
2 Replies
You have no clue.
Posted Jun 10, 2008 03:28 PM by theinternetmaster
1 Replies

Make a New Comment

You must log in in order to post a comment.

Related Resources

Jim Mischel"Highly unlikely" does not mean "impossible"
By Jim MischelJuly 18, 2009 No Comments

One of my programs crashed the other day in a very unexpected place.  A call to System.Threading.ConcurrentQueue.TryDequeue (from the Parallel Extensions to .NET) resulted in an OverflowException being thrown.  Investigation revealed a pretty serious bug in the System.Random constructor.

It's Here; Put Away Your Pre-Conceptions on What an OS Must Be: Part II
By John TraenkenschuhMay 24, 2009 No Comments

In the last blog in this series, Traenk relates his first experiences with computers and with coding.  But now, some years have passed. . .

It's Here; Put Away Your Pre-Conceptions on What an OS Must Be: Part I
By John TraenkenschuhMay 24, 2009 No Comments

Traenk relates his past experience with Operating Systems that goes back 25 years, ok, more than that but he ain't tellin'

See More Blogs

Informit Network