Soap films between pegs relax into Steiner trees, meeting at 120 degrees.
Pegs between two glass plates are dipped in soap, and the film left behind shrinks its area, which here means the total length of the network seen from above. The program keeps that network as a graph of fixed pegs and free junctions and moves every junction along the sum of its films' unit vectors, the gradient of total length. Topology changes when the geometry calls for it: a junction that reaches a peg merges into it, a peg whose films meet at less than 120 degrees splits off a new Steiner point, and a film that shrinks to nothing between two junctions flips the other way, as in a foam, and two films dragged across each other fuse where they touch. The result is always a local minimum, so re-dipping from a random tree can land on a different answer, and the panel compares it with the minimum spanning tree and the best seen. Films are drawn as ribbons between the plates with true thin-film interference colors, thick and pale when fresh and draining into bright bands as they age.
Try it. Drag pegs and watch the network jump between minima. Click empty glass to add a peg, double-click a peg (or press Delete while hovering) to remove it. R re-dips from a random tree, V switches to a top view with the angles labeled, the arrow keys turn the plates, and keys 1 to 6 load layouts.
Paste this into Claude Code, Codex or any coding agent to get a simple version running, then take it wherever you like.
Build a soap film Steiner tree simulator with JavaScript and the HTML canvas element: pegs connected by films that relax into the shortest network, meeting at 120 degrees. Put everything in a single index.html file with no libraries or build step, so I can open it directly in a browser.
Start simple:
- Make a canvas that fills the window on a dark background, viewed from above.
- Place about six pegs, and connect them with a minimum spanning tree (Prim's algorithm). Draw each connection as a glowing line and each peg as a circle.
- Add free junction points: whenever two lines leave a peg at less than 120 degrees, replace them with a new junction just outside the peg, joined to the peg and to both far ends.
- Each frame, move every junction a small step along the sum of the unit vectors toward its neighbors. That is gradient descent on the total length, and the junctions settle where three lines meet at 120 degrees.
- Remove a junction that ends up with only two lines, and merge a junction into a peg when it gets very close.
- Show the total length next to the spanning tree's length.
Once that works, make it beautiful:
- Let the user drag pegs, and handle the case where the line between two junctions shrinks to nothing: merge them and split the four lines the other way (a T1 flip), so the network can jump to a new shape.
- Add a re-dip button that starts from a random spanning tree, to show that different starts give different local minima.
- Draw arcs with the angle at each junction.
Explain the geometry 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 drawing the films as ribbons between two glass plates in a tilted view, thin-film interference colors, or a brute-force search for the true minimum on small inputs.