Five grids of parallel lines dualize into a living Penrose tiling of stained glass.
Five families of parallel lines at 72 degree steps cut the plane into meshes. Labeling each mesh by how many lines of every family lie below it, and putting a corner at the matching sum of five unit vectors, turns every crossing of two lines into a rhomb: de Bruijn's dual method. With the five offsets summing to zero the result is a true Penrose tiling, with thick and thin rhombs in the golden ratio and ruby stars where five thick rhombs meet. Sliding the offsets in the 'perpendicular' direction (a phason shift) flips whole worms of rhombs at once, and they glow as they change. Deflation splits every rhomb into two Robinson triangles, oriented by the de Bruijn index of its corners, cuts each by the golden ratio and zooms in by phi.
Try it. Drag to shift the five grids and watch rhombs flip. Hover a grid line to light up its ribbon of rhombs. Click (or press D) to deflate around that point, up to four times in a row (clicking mid-zoom jumps straight to the next level, and a fifth click comes home); drag or press Space to return to the live pentagrid. G toggles the grid lines, S switches between stained glass and terrazzo, and the arrow keys nudge the offsets.
Paste this into Claude Code, Codex or any coding agent to get a simple version running, then take it wherever you like.
Build a Penrose tiling with de Bruijn's pentagrid method, using 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.
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.
- Define five unit vectors e_j at angles 2 pi j / 5 and five offsets g_j that sum to zero.
- The grid lines are x . e_j + g_j = k for integers k. For every pair of families r < s and every pair of integers (kr, ks) in a modest range, solve the 2 by 2 system for the crossing point x.
- At that crossing, for every other family j compute K_j = ceil(x . e_j + g_j), and set K_r = kr, K_s = ks. The tile corner is V = sum of K_j e_j, and the tile is the rhomb with corners V, V + e_r, V + e_r + e_s, V + e_s. Rhombs from neighboring families (72 degrees apart) are thick; the others are thin.
- Draw every rhomb with an edge of about 30 pixels.
Once that works, make it beautiful:
- Make it stained glass: blue glass for thick rhombs, amber for thin ones, a slight color variation per pane, and thick dark lead lines with a faint highlight.
- Draw the five grid lines faintly on top (they sit about 2.5 times smaller than the tiling), so you can see each line turn into a ribbon of rhombs.
- Let dragging the mouse change the offsets along cos(4 pi j / 5) and sin(4 pi j / 5), which keeps their sum at zero, rebuilding every frame so tiles flip as you move.
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 highlighting the ribbon under the mouse, deflating the tiling with Robinson triangles, or coloring the five-pointed stars.