"The Algorithmic Beauty of Plants" book describes a way to represent procedural surface models by making turtle draw polygons.
(with-graphics (iteration-count 18) (set-axiom (turn(-80) A)) (add-rule (A -> forward(100) turn(20) A))) |
This example draws the familiar outline of a regular polygon.
(with-graphics (iteration-count 18) (set-axiom ({ turn(-80) A })) (add-rule (A -> edge(100) turn(20) A))) |
This example draws the polygon itself. Here are command explanations:
Each polygon must start with
{
- start polygon shape }
- end polygon shape dot
- draw polygon point edge
- draw polygon edge
{
and must end with
}
, {
and }
can be nested.
In between {
and }
there must be at least
three dot
or edge
commands.
(edge(x))
is essentially the same as
(jump(x) dot)
. The reason why dot
is separated is that normal vector for a polygon vertex is assumed
to be turtle's current local Y axis. Perhaps it is convenient
to change turtle orientation before issuing dot
,
for example (jump(100) turn(10) dot turn(10) jump(100) ...)
.
There are times when it is necessary to destroy whole branches —
erase lots of different symbols at once. For that there is a
rip
command which erases everything up until matching
closing square bracket. Consider example:
which rewrites in the following manner:(with-debug (iteration-count 2) (set-axiom (B C C [ C X C B [ B B C ] C B ] C C B)) (add-rule (B -> B)) (add-rule (C -> C)) (add-rule (X -> Y)) (add-rule (Y -> rip)))
In L-systems similar to the one in chapter four where weights of branches are propagated,
axiom: (B C C [ C X C B [ B B C ] C B ] C C B)
p1: (B C C [ C Y C B [ B B C ] C B ] C C B)
p2: (B C C [ C ] C C B)
rip
command could be used to snap branches that get too heavy.
LISP makes it possible to pass down rules as arguments:
This code produces same circle outline that is shown above.(with-graphics (iteration-count 19) (set-axiom (turn(-80) A)) (add-rule (A -> meta-rule(#'F 100) meta-rule(#'turn 20) A)) (add-rule (meta-rule(rule parameter) -> funcall(rule parameter))))
(back to contents)(add-rule ((delay(rule args time) ? (> time 0) -> delay(rule args (1- time))) (delay(rule args time) ? (= time 0) -> apply(rule args))))