Creative Coding Blog

Maths, coding and art

Spirographs II

In a previous post we saw how to draw simple Spirographs. This time we will look at overlaying several curves to create a more complex design. You can achieve different effects by choosing curves which are similar or dissimilar, using colour and transparency, and applying rotations.

Creating families of similar curves

As we saw at the end of the previous article, the number of times the small circle has to rotate around the inside of the large circle to complete the shape is given by:

B/GCD(A, B)

It turns out that the number of “petals” in the shape is given by

A/GCD(A, B)

However, the value of D doesn’t enter into these equations at all. Making small changes to D tends to make small changes to the overall shape, and this is a good way to create families of similar curves. In this case, we are using “similar” in the everyday sense, not in the geometric sense.

Here is an example:

And 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(64);
    noFill();
    strokeWeight(2);
    
    stroke(128, 255, 128);
    for (int d = 5; d < 120; d+= 5)
      spiro(300, 300, 250, 75, d);
}

This code is exactly the same as the previous article, except for the draw method. In this case we use values A=250 and B=75, which creates a shape with 10 petals. We draw the curve multiple times with D taking values between 5 and 115, in steps of 5. Each time through the loop creates a slightly different shape.

Using two shapes

In this example, we add second series of curves, with 5 petals, overlaying the original curve:

The code is the same as before, except for draw which has a second loop:

void draw()
{
    clear();
    background(64);
    noFill();
    strokeWeight(2);
    
    stroke(128, 255, 128);
    for (int d = 5; d < 120; d+= 5)
      spiro(300, 300, 250, 75, d);
    
    stroke(196, 0, 196);
    for (int d = 10; d < 70; d+= 10)
      spiro(300, 300, 200, 40, d);
}

Using colour

In this image, we vary D as before, but also change the colour of the line gradually from red to blue:

Here is the draw code:

void draw()
{
    clear();
    background(64);
    noFill();
    strokeWeight(2);
    
    for (int i = 0; i < 20; i++)
    {
      stroke(255-i*12, 0, i*12);
      spiro(300, 300, 240, 64, 20 + 5*i);
    }
    
 }