Creative Coding Blog

Maths, coding and art

Motifs on Lissajous figures

In the earlier section Lissajous figures with Processing we saw how to create various shapes with the basic Lissajous figure formula.

In this article, instead of just tracing the curve, we will draw a shape at regular points along the curve. We call this repeated shape a motif, and it really can be anything you like. It can also change as you progress along the curve, for example rotate, change size or change colour.

If we make the motif quite large, the motifs from different parts of the curve will overlap, creating interesting effects, and almost completely disguising the original shape of the curve.

A line motif

As an illustration, here is the Lissajous curve for A = 3 and B = 2. In the second curve we show the same figure, but instead of tracing the figure we draw a horizontal line at different points along the curve.

To add a bit more interest, we can rotate the line as we go around the shape. In this case we will apply a rotation of A*t where t is the parameter in the Lissajous figure equations.

The left hand image shows this effect with a short line. The right hand image shows the effect with a longer line. With a longer line, notice how the original shape of the curve is much less obvious, and instead you mainly see the intersections of the lines.

Creating an image

The image below is based on the previous images:

We have improved it by:

  • Adding more lines
  • Making the lines partly transparent so that the image appears lighter where they overlap.

Here is the complete code:

void motif()
{
    noFill();
    strokeWeight(2);
    stroke(128, 196, 255, 64);
    line(-100, 0, 100, 0);
}

void lissajous(float r, float cx, float cy, float A, float B)
{
    for (float t = 0; t < TWO_PI; t += 0.01)
    {
        float x = cx + r * cos(A*t);
        float y = cy + r * sin(B*t);
        pushMatrix();
        translate(x, y);
        rotate(A*t);
        motif();
        popMatrix();
    }
}

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

void draw()
{
    clear();
    background(0);
    
    lissajous(150, 300, 300, 3, 2);
}

The motif function draws the motif - a horizontal line centred at (0, 0). We will use transformations to draw the line at an angle.

The lissajous function traverses the Lissajous curve in the usual way, with t stepping by 0.01 each time. This step size determines how many lines will be drawn, the smaller the step the more lines will be drawn.

On each pass through the loop, the function does the following actions:

  • Calculates the loop point, (x, y).
  • Translates to (x, y). This means that when we draw the motif with coordinates centred on (0, 0) it will be appear at (x, y).
  • Rotates by A*t, This means that when we draw the motif horizontally, it will appear rotated by A*t radians.
  • Calls motif to draw the line.

Notice that we call pushMatrix before doing the transformations. This saves the current state. We then call popMatrix after drawing the line, which undoes the transformations and sets the drawing matrix back to how it was before.

Try this code using different colour schemes, or different values for A and B. You could also vary the rotation of the motif - rather than calling rotate(A*t), try using B*t or some other multiplier.

Using colour

Now we will add a bit more colour. Instead of drawing a blue line, we will draw a line that is half red, half green.

Here is the result:

The basic code change is in the motif function, where we draw the line in two sections with different colours. We also change A and B, but of course you can experiment with different values and different line colours. Here is the code

void motif()
{
    noFill();
    strokeWeight(2);
    stroke(128, 0, 0, 128);
    line(-100, 0, 0, 0);
    stroke(0, 128, 0, 128);
    line(0, 0, 100, 0);
}

void lissajous(float r, float cx, float cy, float A, float B, float P)
{
    for (float t = 0; t < TWO_PI; t += 0.01)
    {
        float x = cx + r * cos(A*t + P);
        float y = cy + r * sin(B*t);
        pushMatrix();
        translate(x, y);
        rotate(B*t);
        motif();
        popMatrix();
    }
}

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

void draw()
{
    clear();
    background(255);
    
    lissajous(170, 300, 300, 5, 3, 0);
}