Fractal Stars — how it works

Romanesco. Every floret is a smaller copy of the head, and every floret of a floret is smaller still. Nothing in the plant knows what the whole is shaped like — it only knows the rule.
One rule
Start from a single point. Place its children evenly on a circle around it, one step away. Then treat every child as a parent and repeat, with the step shrunk by the step factor and the whole generation turned by the deflection.
That is the entire construction. Four numbers decide everything:
| Children | how many points spawn from each — the rotational symmetry. 1 gives a spiral, 2 a branching curve, 3 and up a star. |
| Generations | how many times the rule is applied. Cost grows as children^generations. |
| Step factor | how fast the step shrinks. Below 1 the figure converges; at or above 1 it runs off the page. |
| Deflection | how far each generation twists against its parent, in units of the base angle 2π / children. |
No coordinates are ever written down. The figure is recomputed from those four numbers on every render, so there is no stored geometry that could disagree with the parameters beside it.
Where the sixteen come from
Twelve are the notebook's own — the Systemorph Cloud Fractal Stars notebook shipped
FractalParameters for Fractal star 1 … 12, of which it named four: Sierpinski triangle,
Koch's snowflake, Golden section triangle and Cesàro–Peano, square filling. The other
eight arrived here with names because a figure you can only refer to by number is a figure nobody
talks about; each note says which star it was.
Four more are new — Peacock Seven, Fractal Feather, Patchwork Squares and Triangular Scrub — chosen to sit just off the classical constants, which is where the interesting figures live.
The irrational step factors are exact and that matters. Koch steps by 1.0/3.0, not 0.333; the
golden-section triangle by (√5−1)/2; the quadruple cross by (√6−√2)/2 = 2·sin 15°. Round any of
them and the sub-figures stop meeting, leaving visible seams. A test pins the constants.
Languages
Every word the control says exists in English and German, in
FractalTexts — one pure table per language, the same shape as EduTexts / StoreTexts. The page
picks its language from ?lang=de first, then the viewer's profile locale, then English; a 🌐 line
above the figure switches between them. Figure NAMES are not translated: they are also the ?figure=
URL parameter, so a link means the same thing whoever sends it.
Adding a language is one entry in Supported, one table, and nothing else — the tests then require
that every one of the sixteen figures is explained in it, that it is not a copy of English, and that
every derived phrase still formats.
One control
There used to be three routes — a gallery, a playground and a guided walkthrough — and moving between them meant leaving the figure you were looking at. There is now one screen, and picking an example and inventing your own are the same act done to the same figure:
┌──────────────────────────────────────────────┐
│ the figure, drawing itself │ ← generation by generation
├──────────────────────────────────────────────┤
│ children 5 gens 6 step .407 twist .27 │ ← the four numbers, always here
│ [ Draw ] [ 🎲 Surprise ]│
├──────────────────────────────────────────────┤
│ ‹The rule› ‹Examples› ‹Try yourself› │
└──────────────────────────────────────────────┘
| Area | What it is |
|---|---|
| Show (default) | The whole control. ?figure=Koch's Snowflake opens on a named figure; ?size=900 enlarges; ?lang=de picks the language. |
| Play | The same control. The old playground route, kept alive so no link, bookmark or embed 404s. |
| Tests | The maths suite, executed on the mesh. |
Three things about it are deliberate, and each replaces something that used to annoy:
- You land on a RANDOM figure. No
?figure=, and the page rolls one — so it is a different figure every time you open it and nobody has to press anything to see the thing work. An explicit?figure=still wins, and the roll happens once on the render turn, so a node re-emission cannot swap the figure out from under you mid-read. - The figure DRAWS ITSELF.
FractalMath.ToSvggroups the nodes by generation and fades each one in when its turn comes — SMIL keyframes computed server-side, no script and no timer, the same technique the pendulum and the orbits use. You watch the rule being applied instead of arriving at its result. Thumbnails passrevealSeconds: 0: sixteen figures animating at sixteen rates is a fairground, not a picker. - It redraws on the BUTTON, not the keystroke. That is what makes the numbers explorable — you can set three of them wrong on the way to setting the fourth right without the page thrashing through every half-typed value. The canvas listens to a draw TICKET and merely reads the numbers; typing changes the numbers, pressing changes the ticket.
The figure carries no name of its own: FractalContent.NameOf recognises it by its four numbers.
So a figure loaded from the picker is called Koch's Snowflake and gets Koch's note, and the moment a
number is nudged off it, it quietly stops being Koch — which is the honest answer, and something a
name carried along in the settings could not give.
Everything is write-free: the numbers live in the layout area's own /data, which is per
session. Nothing is written to any node, so an anonymous visitor can use all of it and two viewers
can never fight over what is on screen.
The one thing to be careful about
Growth is children ^ generations. Twelve children over eight generations is 4×10⁸ points, which
would hang the render. FractalMath.MaxNodes caps it at 20 000 and
the figure reports that it was truncated — a pinned test asserts both, because a silent cap
would quietly draw the wrong picture and look deliberate.
The settings clamp every field before the renderer sees it (FractalSettings.ToContent). That
clamp is load-bearing rather than defensive: the generated number field does not enforce
[Range], so a pasted NaN or a negative generation count arrives exactly as typed.
Authoring a node
Content is only the four parameters plus an optional preset name, so a node that means a particular figure is two lines:
{ "nodeType": "FractalStars/Figure",
"content": { "$type": "FractalContent", "preset": "Koch's Snowflake" } }
Naming a preset fills in the numbers; giving numbers explicitly is the other way to say it. Either way the node pins that figure and the page opens on it.
A node that authors nothing rolls a figure instead — which is exactly what the showcase node
(FractalStars/Stars) does, and why it is a different figure every time you open it. The edge is
deliberate: a node whose numbers happen to be exactly the defaults counts as having chosen nothing,
because those defaults are what an unauthored node carries. A node that really wants them says
"preset": "Fractal Rose", which is the same figure.
What came from where
| Systemorph Cloud | MeshWeaver |
|---|---|
IFractalCustom : IMutableScope with [DefaultValue] parameters |
FractalSettings + host.Edit(...) |
interactiveObject.CreateEditor(...) / CreateView(...) |
a layout area over the node stream and the form's data stream |
ChartBuilder.Bubble() |
generated inline SVG in Controls.Html |
| notebook cells re-run by hand | reactive re-render on every emission |
| nothing | Figure/Test/*.cs + a Tests area, executed in CI |
Original notebooks: Fractal Stars and Fractal Stars — Interactive Object, Systemorph Cloud. Rebuilt for MeshWeaver in 2026.