Draw My Canvas / studio

Apollonian Gasket

Drop the biggest circle that fits into every gap. Repeat. A 2,200-year-old construction, turning.

Plate 13circle-packing
Live on an HTML canvas · vanilla JavaScript · no dependencies Open fullscreen

About this piece

Three circles that all touch each other, sitting inside a fourth that they all touch from within. That leaves four gaps. Drop the largest circle that fits into each gap; it necessarily touches all three of its neighbours, and leaves three smaller gaps behind. Repeat forever and you have an Apollonian gasket, named for Apollonius of Perga, who set the underlying tangency problem around 200 BC.

What is left when you have removed every circle has zero area and is still uncountably infinite — a fractal dust with Hausdorff dimension about 1.3057. That number has no closed form anyone has found; it is a numerical result.

How the circles are found

Descartes’ circle theorem relates the curvatures of four mutually tangent circles. Curvature is 1/radius, and it is negative for the one the others sit inside — that sign is the whole trick that lets the outer boundary fall out of the same arithmetic as everything else:

(k₁ + k₂ + k₃ + k₄)² = 2(k₁² + k₂² + k₃² + k₄²)

Solve that quadratic for k₄ and you get two roots, both of them real circles: the gap circle you want, and the one you already had. So this piece never solves it. Given a tangent quadruple, the other circle tangent to any three of them is just the reflection of the fourth — and the identical relation holds for the products of curvature and centre, so the position comes out the same way:

k′ = 2(k₁+k₂+k₃) − k₄
k′z′ = 2(k₁z₁+k₂z₂+k₃z₃) − k₄z₄

No square root, so there is no branch to pick and nothing for floating point to drift on. Every circle you can see came out of those two lines, and it holds up: run the recursion down to radius 0.006 of the disc and it yields 329 circles, of which the one reaching furthest out has |centre| + radius = 1.000000000000001. After twenty levels of feedback, double precision is off by one part in 1015.

What to look for

The packing is built once and cached; a frame is only a rotation and a re-stroke of the same table, plus one slow brightness wave running outward through the recursion depths. Building that table for a 1280×900 window takes about 2 ms and yields 911 circles. Doing it sixty times a second — 120 ms of arithmetic per second, for a table whose contents cannot have changed — is the difference between a plate you can leave running on a phone and one you cannot.

Depth is capped by a minimum on-screen radius of about one pixel, not by a fixed level. A 390×844 phone therefore builds 329 circles where a 1280×900 desktop builds 911: a shallower gasket rather than the same one rendered badly. Widen the window and new circles genuinely appear.

Honest limits: this is the symmetric gasket, seeded from three equal circles. Apollonian packings exist for any tangent starting triple, and the lopsided ones are arguably more interesting to look at — they just do not sit as well inside a rectangular frame you did not choose. And because the disc is round and your iframe probably is not, there is empty paper at the sides on a wide window. Reduced-motion visitors get the packing drawn once, held still.

Curious how the loop and canvas fit together? Read how it works →