Creative Coding Blog

Maths, coding and art

Spirographs

Spirograph is a toy which uses plastic cogs and a biro to plot complex patterns.

In this series we will learn how to create Spirograph patterns in Processing.

Spirographs

Here is a Spirograph toy:

Image by Multicherry

The idea is that you pin one of the large plastic rings to a piece on paper on a flat cork board. You then put one of the plastic circles inside the plastic ring, and put a ball pint pen through one of the holes. As you push the plastic circle round the inside of the plastic ring, the pen traces out a pattern (often a rose type shape). Depending on the size of the plastic circle, and which hole you put the pen in, there are a variety of different shapes. You can also overlay multiple patterns, perhaps in different colours, to make more complex designs.

How Spirograph patterns work

Here is an animation of a spirograph pattern being created.

The basic idea is that you have a large circle of radius A and smaller circle of radius B that rolls around inside it. The pen, as a distance D from the centre od the smaller circle, traces out the curve.

A Spirograph curve is a type of Hypotrochoid curve. We will need the equations from that section to implement a Spirograph in code.

Read the article, on schoolcoders.com, if you want to know more about the equations. Here are the equations in code:

x = cx + (A - B) * cos(t) + D * cos(t*(A - B)/B)
y = cy + (A - B) * sin(t) - D * sin(t*(A - B)/B)

Here A, B and D are the constants above. cx and cy give the position of the centre of the main circle.

Example

Here is an example Spirograph:

Here is the code:

int GCD(int a, int b)
{
   if (b==0)
     return a;
   return GCD(b,a%b);
}

void spiro(float cx, float cy, int A, int B, int D)
{
    PShape s = createShape();
    s.beginShape();
    for (float t = 0; t < TWO_PI*B/GCD(A, B); t += 0.01)
    {
        float x = cx + (A - B) * cos(t) + D * cos(t*(A - B)/B);
        float y = cy + (A - B) * sin(t) - D * sin(t*(A - B)/B);
        s.vertex(x, y);
    }
    s.endShape(CLOSE);
    
    shape(s);
}

void setup()
{
    size(600, 600);
}

void draw()
{
    clear();
    background(255);
    noFill();
    strokeWeight(2);
    
    stroke(255, 0, 0);
    spiro(300, 300, 360, 150, 85);

This code is quite similar to the code for Lissajous figures, except that the spiro function implements the Spirograph calculations (rather than the Lissajous figure calculations).

The other difference us that the upper limit of t is:

TWO_PI*B/GCD(A, B)

We will look at why this is below.

Multiple rotations

Take another look at the animation at the start of the article. The small red circle rotates around the inside of the large red circle, drawing the curve as it goes.

But if you watch carefully, you will see that the curve isn’t complete after the first rotation. That is because, although the small circle has arrived back in its original position, the blue dot that traces out the curve is in a different place. The red circle has to go round 4 times before the blue dot arrives back at its original position.

In fact, the number of rotations depends on the value of A and B in a less than obvious way. To create a complete curve the inner circle needs to go round a total of B/GCD(A, B) times, where GCD is the greatest common divisor function. Since Processing doesn’t have a built in GCD function, we have included a simple implementation in the source file.