Soap foam coarsens under von Neumann's exact law, with live T1 swaps and vanishing cells.
A flat soap foam ages: gas leaks through each film from small, high pressure bubbles into big ones, so the foam coarsens. Because films meet in threes at 120 degrees, a bubble's area changes at a rate set only by its number of sides, dA/dt = K (n - 6), one of the few exact laws in physics, and the panel plots every bubble's measured rate against that line while mean area grows linearly in time. The foam is a Laguerre (power) tessellation on a torus: each frame advances every target area by the law, solves the cell weights with damped Newton steps so the cells match those areas, and nudges generators toward their centroids to relax the junctions. Neighbor swaps (T1, flashed gold) and the disappearance of three-sided bubbles (T2, white sparks) fall out of the tessellation, films are drawn as arcs bent by the Laplace pressure difference, and the iridescence comes from a thin-film interference table integrated against CIE color matching functions.
Try it. Click a film to rupture it and merge the two bubbles, then watch the big many-sided bubble swallow its neighbors. Drag to shear the foam and trigger T1 swaps, press S to shake it, C (or the toggle) to color bubbles by side count, plus and minus to change speed, and Space for fresh foam.
Paste this into Claude Code, Codex or any coding agent to get a simple version running, then take it wherever you like.
Build a coarsening 2D soap foam with JavaScript and the HTML canvas element. Put everything in a single index.html file with no libraries or build step, so I can open it directly in a browser.
The physics: gas diffuses from small bubbles into big ones, and von Neumann's law says a bubble's area changes at a rate set only by its number of sides n: dA/dt = K (n - 6).
Start simple:
- Make a canvas that fills the window, stays sharp on high-DPI screens (scale by devicePixelRatio), and resizes with the window. Paint it near black.
- Scatter about 300 points, each with a weight w and a target area from a wide random spread.
- Represent the foam as a power diagram (weighted Voronoi). Build each cell by clipping a big square around its point with the half plane |p - xi|^2 - wi <= |p - xj|^2 - wj for every other point (brute force is fine). Remember which neighbor made each edge.
- Each frame: count each cell's sides, grow its target area by K (n - 6) dt, and nudge its weight by (target - area) divided by the sum of edge length / (2 x neighbor distance). Move each point a third of the way to its cell's centroid so junctions relax toward 120 degrees.
- When a target area gets tiny, delete that bubble and share its area with its neighbors.
- Draw the outlines as thin white lines.
Once that works, make it beautiful:
- Fill each bubble with a dark radial gradient that turns clear at the rim, over a soft rainbow backdrop, so rims look iridescent, plus a small white highlight.
- Click a film to merge its two bubbles, and toggle coloring by side count.
- Plot each bubble's measured dA/dt against n so the straight line of the law appears.
Explain the key ideas in short code comments. When you're done, tell me how to open it and suggest three directions I could take it next, such as a spatial hash grid for thousands of bubbles, films curved by the pressure difference across them, or wrapping the foam on a torus so there are no walls.