Scrolls, acanthus leaves and flowers grow to fill any frame, like an engraver's panel.
This follows Wong, Zongker and Salesin's adaptive floral ornament. An occupancy grid holds the frame and everything placed so far, and an exact Euclidean distance transform turns it into the radius of the largest empty circle at every point. It starts from a seed structure (a stalk crowned by a palmette, or for round frames a central rosette with palmette-tipped spokes along the mirror axes), then each step takes the biggest hole and fills it with an element attached to an existing stem: big holes get a scroll, a Bezier branch that leaves its parent at an angle and winds into the hole as a tangent-continuous logarithmic spiral, often ending in a flower; medium holes get a lobed acanthus leaf or a hair-thin tendril; small ones get berries. A candidate is accepted only if every sample of its tapered outline clears the distance field, so nothing touches. Growth happens in one half or one quadrant and is mirrored, then replayed in placement order, structure first and filigree last.
Try it. Draw a closed shape anywhere to make your own frame and watch ornament fill it (Mirror makes it bilaterally symmetric). Choose a cartouche, medallion, quatrefoil or arch, switch between engraving, gilt, nouveau and delft styles, and click or press Space to regrow from a new seed.
Paste this into Claude Code, Codex or any coding agent to get a simple version running, then take it wherever you like.
Build a generative floral ornament that fills a frame with spiraling vines, in the spirit of Victorian engraved panels, 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 a warm paper color and draw an oval frame in dark ink.
- Keep a list of placed circles (center and radius) that stand in for everything drawn so far. To find where to grow next, sample a few thousand random points inside the frame and pick the one whose distance to the nearest circle or to the frame edge is largest: that is the largest empty circle.
- Fill it with a spiral scroll: a curve that starts at the nearest point of an existing stem and winds into the empty circle as a logarithmic spiral (radius shrinking by a constant factor per turn). Draw it as a tapered ink line, thick at the base and thin at the curl, and record circles along it as occupied.
- Repeat, getting smaller each time, until no empty circle is bigger than a few pixels. Animate it so each new scroll draws itself.
Once that works, make it beautiful:
- Grow only the left half and mirror every element, so the panel is symmetric.
- Mix element types by hole size: scrolls for big holes, a pointed leaf with a midrib and fine hatching for medium ones, small berries for the smallest.
- Make the branch join its parent smoothly: leave the stem at an angle and use a cubic Bezier whose end tangent matches the spiral's tangent where it begins.
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 an exact distance transform on a grid instead of random sampling, letting the user draw their own frame, or gold-on-velvet and blue-and-white tile color schemes.