In the previous post, I used a straight-forward data format to define Lindenmeyer systems. Here I'll draw a few more L-system fractals, starting with the space-filling Hilbert curve:
(def hilbert-curve
'{:axiom [A]
:rules {A [+ B F - A F A - F B +]
B [- A F + B F B + F A -]}
:moves {+ [:turn 90]
- [:turn -90]
F [:forward 1]}})
which at the fifth level of recursion looks like this:
Here's the Koch curve, two levels deep:
(def koch-curve
'{:axiom [F + F + F + F]
:rules {F [F + F - F - F F + F + F - F]}
:moves {+ [:turn 90]
- [:turn -90]
F [:forward 1]}})
A SierpiĆski triangle, at seven levels:
(def sierpinski-triangle
'{:axiom [A F]
:rules {A [B F - A F - B]
B [A F + B F + A]}
:moves {+ [:turn -60]
- [:turn 60]
F [:forward 1]}})
And the dragon curve, at 11 levels:
(def dragon-curve
'{:axiom [F X]
:rules {X [X + Y F +]
Y [- F X - Y]}
:moves {+ [:turn -90]
- [:turn 90]
F [:forward 1]}})
You can find more fractal-generating L-systems in this Observable, including Penrose tiles and asymmetrical plant-like forms, which rely on nesting contexts that aren't supported by the scheme here. One of my favorites from Kelley's post is the hexagonal gosper:
(def hexagonal-gosper
'{:axiom [X F]
:rules {X [X + Y F + + Y F - F X - - F X F X - Y F +]
Y [- F X + Y F Y F + + Y F + F X - - F X - Y]}
:moves {+ [:turn -60]
- [:turn 60]
F [:forward 1]}})
I haven't given much thought to how I'd support nesting contexts with this data-driven approach. For the moment I'd like to explore in a different direction.