Lissajous Curves
About This Sketch
Named after French physicist Jules Antoine Lissajous, these elegant curves emerge from the intersection of two perpendicular sine waves. The 3:4 frequency ratio creates a pattern that loops and weaves through itself.
Lissajous curves appear in physics and engineering—oscilloscopes display them when analyzing signals, and they describe the motion of pendulums and vibrating strings. The mathematical simplicity (just two sine functions) belies their visual complexity.
Algorithm
Lissajous curves are parametric curves created by combining two perpendicular harmonic oscillations with different frequencies. They create beautiful, complex looping patterns.
**Key Concepts:**
- **Parametric Equations**: x = A sin(at + δ), y = B sin(bt)
- **Frequency Ratio**: a:b determines the curve's complexity
- **Phase Difference**: δ affects the curve's shape and orientation
- **Harmonic Motion**: Two independent sine waves combined
**How it works:**
1. Choose frequency ratio (3:4 creates complex loops)
2. For each time step, calculate x using sine with frequency a
3. Calculate y using sine with frequency b
4. Phase shift (delta) rotates the entire pattern
5. Store points to draw trailing path
6. Fade older points for motion trail effect
7. The curve repeats when both oscillations complete cycles
Pseudocode
SETUP:
t = 0
path = empty array
a = 3 // x frequency
b = 4 // y frequency
delta = π/4 // phase shift
DRAW (every frame):
CLEAR background with transparency
x = canvas_center_x + amplitude × sin(a × t + delta)
y = canvas_center_y + amplitude × sin(b × t)
ADD (x, y) to path
IF path.length > 300:
REMOVE oldest point
FOR i = 0 to path.length:
opacity = map(i, 0, path.length, 0, 255)
color = gradient based on i
DRAW line segment to path[i]
DRAW point at current (x, y)
t = t + 0.03
Source Code
let sketch = function(p) {
let t = 0;
let path = [];
p.setup = function() {
p.createCanvas(400, 300);
p.colorMode(p.RGB);
};
p.draw = function() {
const colors = getThemeColors();
p.background(...colors.bg, 20);
// Parameters for Lissajous curve
let a = 3; // x frequency
let b = 4; // y frequency
let delta = p.HALF_PI / 2; // phase difference
// Calculate current position
let x = p.width/2 + 120 * p.sin(a * t + delta);
let y = p.height/2 + 100 * p.sin(b * t);
// Add to path
path.push({x: x, y: y});
if (path.length > 300) {
path.shift();
}
// Draw path
p.noFill();
p.beginShape();
for (let i = 0; i < path.length; i++) {
let pt = path[i];
let alpha = p.map(i, 0, path.length, 0, 255);
let colorProgress = i / path.length;
let col = colorProgress < 0.5 ?
colors.accent1.map((c, idx) => p.lerp(c, colors.accent2[idx], colorProgress * 2)) :
colors.accent2.map((c, idx) => p.lerp(c, colors.accent3[idx], (colorProgress - 0.5) * 2));
p.stroke(...col, alpha);
p.strokeWeight(2);
p.vertex(pt.x, pt.y);
}
p.endShape();
// Draw current point
p.fill(...colors.accent2);
p.noStroke();
p.circle(x, y, 8);
t += 0.01;
};
};