🎨 Mathematics · Parametric Curves
📅 April 2026⏱ 12 min🟡 Beginner–Intermediate

Spirographs, Hypotrochoids & Epitrochoids: The Maths of Rolling Circles

A spirograph toy traces the path of a point on a small gear rolling inside or around a larger ring. The result is never quite circular — instead it produces intricate petalled curves whose exact shape depends on a single ratio of integers. Behind this childhood toy lies a beautiful branch of geometry connecting gear ratios, greatest common divisors, Fourier series, and planetary motion in a single unified picture.

1. The Cycloid: Rolling on a Line

Before gears, consider the simplest rolling-circle curve: fix a circle of radius r rolling along a straight line without slipping. A point on the rim traces a cycloid:

x(t) = r · (t − sin t) y(t) = r · (1 − cos t) t ∈ [0, 2π] traces one arch of the cycloid (one full revolution). Arc length of one arch: 8r (exactly 4× the diameter — surprisingly clean) Area under one arch: 3πr² (3× the area of the rolling circle)

The cycloid has two famous physical properties. It is the brachistochrone: the curve of fastest descent between two points under gravity — faster even than a straight line. And it is the tautochrone: no matter where on the arch you release a frictionless bead, it reaches the bottom in exactly the same time (Huygens, 1659). This made the cycloid the basis of the first accurate pendulum clock escapement.

If the tracing point is not on the rim but inside (at distance d < r) or outside (d > r), the curve is a prolate or curtate cycloid respectively — smoother loops or cusped arches depending on d.

2. Hypocycloids: Rolling Inside a Circle

Now roll the small circle inside a fixed outer circle of radius R. The tracing point is on the rim of the small circle (radius r). The resulting curve is a hypocycloid:

x(t) = (R − r) · cos t + r · cos((R−r)t/r) y(t) = (R − r) · sin t − r · sin((R−r)t/r) Special cases (pretty names for integer R/r ratios): R/r = 2 → straight line segment (degenerate case) R/r = 3 → deltoid (3-cusped, triangular) R/r = 4 → astroid (4-cusped, x^(2/3) + y^(2/3) = R^(2/3)) R/r = 5 → pentadeltoid (5 cusps) R/r = 6 → hexadeltoid (6 cusps) Number of cusps = R/r (when R/r is an integer)

The astroid (R/r = 4) appears in many contexts: the evolute of an ellipse is an astroid; the envelope of a moving ladder (one end on a wall, one on the floor) is an astroid. Its equation x^(2/3) + y^(2/3) = R^(2/3) looks deceptively simple for such an intricate geometric object.

Degenerate case R = 2r: When the small gear is exactly half the diameter of the outer ring, the tracing point moves in a perfect straight line back and forth through the centre. This is the basis of the Trammel of Archimedes — a mechanism that converts rotary motion to linear motion, patented as the "do-nothing machine" because it appears to produce only the motion you put in.

3. Hypotrochoids: The Spirograph Curve

A hypotrochoid generalises the hypocycloid by placing the tracing point at distance d from the centre of the rolling circle, not necessarily on the rim:

// Hypotrochoid parametric equations x(t) = (R − r) · cos t + d · cos((R−r)t/r) y(t) = (R − r) · sin t − d · sin((R−r)t/r) Parameters: R = radius of the fixed outer circle r = radius of the rolling inner circle d = distance of tracing point from centre of rolling circle When d = r: hypocycloid (point on rim → cusps) When d < r: inner hypotrochoid (smooth, rounded "petals") When d > r: outer hypotrochoid (loops, self-intersections) This is the curve produced by a standard Spirograph® toy!

The Spirograph toy (invented 1965 by Denys Fisher) provides physical gear sets with specific R and r values. The small gear's pen-holes correspond to different values of d. By choosing different gear combinations and holes, children (and mathematicians) explore this two-parameter family of curves.

Rose Curves as Special Cases

When d = R − r (tracing point at the origin of the rolling circle if it were at the outer rim), the hypotrochoid collapses to a rose curve r = cos(nθ) in polar coordinates, where n = R/r. This is why rose curves with 3, 5, 7 petals have odd denominators — the rolling circle must complete an integer number of full rotations inside the fixed ring.

4. Epitrochoids: Rolling Outside

An epitrochoid results from rolling the small circle outside the fixed circle — a single sign change in the equations:

// Epitrochoid parametric equations x(t) = (R + r) · cos t − d · cos((R+r)t/r) y(t) = (R + r) · sin t − d · sin((R+r)t/r) Special cases (epicycloids, d = r): R/r = 1 → cardioid (heart shape, 1 cusp) R/r = 2 → nephroid (kidney shape, 2 cusps) R/r = 3 → three-cusped epicycloid R/r = n → n-cusped epicycloid The cardioid is also the region of the Mandelbrot set main body!

The cardioid (Greek: heart) is one of the most recognisable mathematical curves. Beyond its appearance as the Mandelbrot set's main body boundary, it is the directrix of a parabolic microphone and the shape of the polar gain pattern of a cardioid microphone element — hence the microphone type's name.

The nephroid appears as the caustic (bright curve) you see on the inside of a cylindrical coffee mug in sunlight. The reflected or refracted rays from the curved surface envelope a nephroid — a natural optical phenomenon explained by epitrochoid geometry.

5. Petal Counting & the GCD Rule

How many petals (lobes) does a spirograph curve have? The answer involves the greatest common divisor (GCD) of the two gear radii:

Let k = R/r (ratio of outer to inner radius, reduced to lowest terms) Write k = p/q where gcd(p, q) = 1 Number of petals (lobes): Hypotrochoid, d < r: p − q petals Hypotrochoid, d > r: p − q loops (same count, different topology) Epitrochoid: p + q petals (outer rolling adds lobes) Alternative form using raw teeth counts T_outer, T_inner: num_petals = (T_outer − T_inner) / gcd(T_outer, T_inner) Examples: R=60, r=36: gcd=12, ratio=5/3 → 5−3 = 2 petals (elongated ellipse) R=60, r=24: gcd=12, ratio=5/2 → 5−2 = 3 petals (triangular) R=60, r=16: gcd=4, ratio=15/4 → 15−4 = 11 petals R=60, r=45: gcd=15, ratio=4/3 → 4−3 = 1 petal (closed loop)

This formula is the mathematical reason why toy spirographs print the number of "teeth" on each gear. Given tooth counts, you can predict the exact pattern before drawing it — or conversely, choose gear combinations to achieve a desired number of petals.

Why GCD? The ratio p/q in lowest terms tells you how many rotations of the inner gear (p rotations relative to the fixed frame) are needed before the system returns to its initial configuration. Each rotation of the inner gear contributes one partial petal; (p−q) net lobes are traced because the angular advance per inner-gear revolution is (R−r)/r = (p−q)/q.

6. Period, Closure, and the LCM

A spirograph curve closes (returns to its starting point) after the parameter t has advanced by 2π × (LCM(R, r) / R) — the time for the system to return to exactly its initial gear alignment. Using gear teeth counts T_R and T_r:

Full period (number of inner-gear rotations until closure): N_inner = T_outer / gcd(T_outer, T_inner) Equivalently, parameter t must go from 0 to: t_max = 2π · T_outer / gcd(T_outer, T_inner) = 2π · (R/r) / gcd(R/r numerator, R/r denominator) Example: R=60, r=24 (gcd=12, reduced = 5/2) t_max = 2π × 5 (inner gear makes 5 rotations → 2 full outer periods → 3 petals drawn) Rule: if R/r = p/q in lowest terms: inner gear rotates p times, outer period repeats q times, p − q (or p + q) petals are drawn.

This means drawing the complete spirograph curve in code requires sweeping t from 0 to 2π × p (where p is the numerator of the reduced gear ratio, not just 2π). Stopping at 2π draws only a partial curve — often a confusing bug when first implementing spirographs.

// JavaScript: draw a complete hypotrochoid function drawHypotrochoid(ctx, R, r, d, steps=2000) { const g = gcd(R, r); const p = R / g; // numerator of reduced ratio const tMax = 2 * Math.PI * p; // full period ctx.beginPath(); for (let i = 0; i <= steps; i++) { const t = (tMax * i) / steps; const x = (R-r)*Math.cos(t) + d*Math.cos((R-r)*t/r); const y = (R-r)*Math.sin(t) - d*Math.sin((R-r)*t/r); i === 0 ? ctx.moveTo(x, y) : ctx.lineTo(x, y); } ctx.stroke(); } function gcd(a, b) { return b === 0 ? a : gcd(b, a % b); }

7. Lissajous Figures: A Special Limit

As the outer circle radius R → ∞ while r stays fixed (gear ratio → ∞), rolling inside a circle locally approximates rolling along a line. In the limit, the hypotrochoid becomes a Lissajous figure — the parametric curve traced by two independently oscillating sinusoids:

x(t) = A · sin(a·t + δ) y(t) = B · sin(b·t) The Lissajous figure has: a/b = frequency ratio of the two oscillations δ = phase difference When a/b = 1, δ = π/2: circle When a/b = 1, δ = 0: diagonal line When a/b = 2/1: figure-eight (parabola envelope) When a/b = 3/2: 3-lobed pretzel shape Closure: curve closes iff a/b is rational (just like spirographs!)

Lissajous figures appear on an oscilloscope when two sinusoidal voltages drive the X and Y deflection plates. The shape immediately reveals the frequency ratio — a circle means equal frequencies, a figure-eight means one frequency doubles the other. This is used in audio labs to tune frequencies and measure phase relationships between signals.

The connection to spirographs is more than formal: both are generated by combining two circular motions. A hypotrochoid combines a circle of radius (R−r) rotating at rate 1 with a circle of radius d rotating at rate (R−r)/r. A Lissajous figure combines a horizontal oscillation (half a circle) at rate a with a vertical oscillation at rate b. The visual similarity — closed petalled curves — reflects this shared circular superposition.

8. Fourier Epicycles: Any Curve from Circles

Spirograph curves are built from two circles. But Fourier epicycles generalise this to any number of circles — and with enough circles, you can approximate any closed curve, not just algebraic ones.

// N-circle Fourier epicycle representation z(t) = Σₙ cₙ · e^(i·nωt) (complex notation: z = x + iy) = c₀ (constant offset) + c₁ e^(iωt) (fundamental: one rotation per period) + c₂ e^(2iωt) (second harmonic: two rotations) + c₋₁ e^(−iωt) (reverse rotation) + ... Each term cₙ e^(inωt) is a circle of radius |cₙ| rotating at rate n. To approximate an arbitrary curve (e.g., drawn with a mouse): 1. Sample the curve as z(t) at N equally-spaced t values. 2. Compute Discrete Fourier Transform: cₙ = DFT(z)[n] / N 3. Render the epicycle chain: each arm rotates at its harmonic frequency. Result: with 50 circles, the chain tip traces almost any closed shape!

This is the basis of the popular "Fourier epicycles drawing" visualisations — where a chain of rotating arms traces out a portrait, a national border, or a handwritten letter. Each arm corresponds to one Fourier mode; the full chain sum approximates the complex Fourier series of the original curve.

The mathematical content is the same as audio Fourier analysis: just as a sound wave is decomposed into frequency components (harmonics), a 2D closed curve is decomposed into circular rotations at different frequencies. The "fundamental frequency" arm goes around once per period; higher harmonics add the fine wiggles and sharp corners.

Convergence: For a smooth curve, Fourier coefficients decay rapidly (|cₙ| ∝ n^(−k) for a k-times differentiable curve). A circle is represented exactly by c₁ alone. A square needs many terms because its corners are discontinuities — the Gibbs phenomenon produces ringing near sharp angles with finite truncation.

9. Drawing Spirographs in JavaScript

A complete, interactive spirograph renderer in under 50 lines:

// HTML: <canvas id="c" width="500" height="500"></canvas> const canvas = document.getElementById('c'); const ctx = canvas.getContext('2d'); const cx = 250, cy = 250; // canvas centre function drawSpirograph(R, r, d, color='#6366f1') { const g = gcd(Math.round(R), Math.round(r)); const periods = R / g; // number of inner rotations const steps = periods * 360; // 1 step per degree const scale = 220 / (R); // fit in canvas ctx.beginPath(); ctx.strokeStyle = color; ctx.lineWidth = 1.2; for (let i = 0; i <= steps; i++) { const t = (2 * Math.PI * periods * i) / steps; const x = (R-r)*Math.cos(t) + d*Math.cos((R-r)*t/r); const y = (R-r)*Math.sin(t) - d*Math.sin((R-r)*t/r); i === 0 ? ctx.moveTo(cx + x*scale, cy + y*scale) : ctx.lineTo(cx + x*scale, cy + y*scale); } ctx.stroke(); } function gcd(a, b) { return b < 0.5 ? a : gcd(b, a % b); } // Examples: ctx.fillStyle = '#0f0f0f'; ctx.fillRect(0,0,500,500); drawSpirograph(100, 60, 50, '#6366f1'); // 2 petals drawSpirograph(100, 40, 60, '#f59e0b'); // 3 petals drawSpirograph(100, 36, 70, '#22c55e'); // irregular

The simulation at Spirograph Simulator on this site lets you interactively drag sliders for R, r, and d, and watch the curve build in real time — with the inner gear visibly rolling around the outer ring to show the geometric construction.

Extensions