Lindenmeyer systems playground
Not long ago I learned about Replicant, so as an excuse to play around with it I created a playground for Lindenmeyer systems based on my previous posts about L-systems. You can use the playground here.
While building it, I added support for pushing and popping states with the [
and ]
operators, which turned out to be relatively straight-forward. The conversion of commands such as [:turn 90]
into a set of points looks like this:
(defmulti update-state (fn [_ [cmd]] cmd))
(defmethod update-state nil [state _]
state)
(defmethod update-state :forward [state [_ param]]
(let [{[x y] :point :keys [heading points]} state
radians (* heading Math/PI (/ 180))
x (+ x (* param (Math/sin radians)))
y (+ y (* param (Math/cos radians)))]
(assoc state :point [x y] :points (conj points [x y]))))
(defmethod update-state :turn [state [_ param]]
(assoc state :heading (- (state :heading) param)))
(defmethod update-state :push-state [state _]
(update state :states conj {:point (state :point) :heading (state :heading)}))
(defmethod update-state :pop-state [state _]
(let [{:keys [point heading]} (-> state :states peek)]
(-> state
(assoc :point point :heading heading)
(update :points conj :move point)
(update :states pop))))
(defn coords [cmds]
(:points
(reduce update-state
{:point [0 0]
:heading 180
:points [[0 0]]
:states []}
cmds)))
Note that when popping the state the list of points gets the non-coordinate value :move
, which is recognized by the drawing code and tells it not to draw a line segment from the previous point to the new point.
I also improved the generation of random L-systems. I've noted some symmetries in the rules of systems that produce pleasing outputs, but in the playground I created symmetries by transforming a randomly generated base rule, then selectively reversing it, inverting it, and concatenating with the original rule to create new, related rules. It will also occasionally insert [
and ]
commands, though not always in a meaningful way (e.g., [+]
). The current system seems to have the best success rate of any of my previous attempts, more frequently generating non-trivial and visually distinctive patterns.
If you have suggestions for further improvements, please let me know.