Documentation |
Lindenmayer systems
This functionality does not run in MATLAB.
plot::Lsys(alpha, start, trans, …, <a = a_{min} .. a_{max}>, options)
plot::Lsys creates Lindenmayer systems, i.e., string rewriting systems controlling turtle graphics.
Lindenmayer systems, or L-systems for short, are based on the concept of iteratively transforming a string of symbols into another string. After a finite number of iterations, the resulting string is translated into a sequence of movement commands to a "turtle" (see plot::Turtle), which can be drawn on the screen.
In plot::Lsys, the string of symbols is represented by a string of characters, i.e., a DOM_STRING. Transformation rules are given as equations mapping strings of length 1 to strings of arbitrary length. Turtle rules are given as equations mapping strings of length 1 to simple movement commands: Line, Move, Left, Right, Push, Pop, Noop, or a color specification.
The commands are mostly self-explanatory. Left and Right turn by the amount set in the slot "RotationAngle"; the initial direction is "up". Line and Move move by the amount set in "StepLength", where Move does not draw a line. Push stores the current state (position, direction, color) on a stack from where it can later be reactivated using Pop. Noop means "ignore this, no operation". A color specification changes the line color.
The following turtle rules are used by default (but can be disabled by giving other rules for the left-hand sides):
"F" = Line, "f" = Move, "[" = Push, "]" = Pop, "+" = Left, "-" = Right.
Attribute | Purpose | Default Value |
---|---|---|
AffectViewingBox | influence of objects on the ViewingBox of a scene | TRUE |
AntiAliased | antialiased lines and points? | FALSE |
Color | the main color | RGB::Blue |
Frames | the number of frames in an animation | 50 |
Generations | number of iterations of L-system rules | 5 |
IterationRules | iteration rules of an L-system | |
Legend | makes a legend entry | |
LegendText | short explanatory text for legend | |
LegendEntry | add this object to the legend? | FALSE |
LineColor | color of lines | RGB::Blue |
LineWidth | width of lines | 0.35 |
LineStyle | solid, dashed or dotted lines? | Solid |
LinesVisible | visibility of lines | TRUE |
Name | the name of a plot object (for browser and legend) | |
ParameterEnd | end value of the animation parameter | |
ParameterName | name of the animation parameter | |
ParameterBegin | initial value of the animation parameter | |
ParameterRange | range of the animation parameter | |
RotationAngle | angle of rotation commands in L-systems | |
StartRule | start rule of an L-system | |
StepLength | length of movement commands in L-systems | 1.0 |
TimeEnd | end time of the animation | 10.0 |
TimeBegin | start time of the animation | 0.0 |
TimeRange | the real time span of an animation | 0.0 .. 10.0 |
Title | object title | |
TitleFont | font of object titles | [" sans-serif ", 11] |
TitlePosition | position of object titles | |
TitleAlignment | horizontal alignment of titles w.r.t. their coordinates | Center |
TitlePositionX | position of object titles, x component | |
TitlePositionY | position of object titles, y component | |
TurtleRules | rules translating L-system symbols to turtle movements | |
Visible | visibility | TRUE |
VisibleAfter | object visible after this time value | |
VisibleBefore | object visible until this time value | |
VisibleFromTo | object visible during this time range | |
VisibleAfterEnd | object visible after its animation time ended? | TRUE |
VisibleBeforeBegin | object visible before its animation time starts? | TRUE |
As a very simple system, we consider the following iteration rule: "replace each line forward by the sequence "line forward, move forward without painting, line forward."":
l := plot::Lsys(0, "F", "F" = "FfF"):
Note that we do not provide an iteration rule for "f". This means "leave f alone, do not change it."
The start state is displayed by plotting the system after zero generations:
l::Generations := 0: plot(l)
Increasing the number of generations, we see the effect of our transformation rule:
l::Generations := 1: plot(l)
l::Generations := 2: plot(l)
l::Generations := 3: plot(l)
The following variant of this simple example produces approximations to the Cantor set:
l := plot::Lsys(0, "F", "F" = "FfF", "f" = "fff"): plot(l)
To get more interesting examples, we include rotations into our rules:
l := plot::Lsys(PI/2, "F-F-F-F", "F" = "F-F+F+FF-F-F+F", Generations = 3)
As you can see, plot::Lsys has detected that our rule is an iteration rule. We could have used this syntax directly when creating the object. We have not given turtle rules, so the defaults are used:
plot(l)
The Peano curve is a famous example of a space filling curve. In the limit process, increasing the number of iterations while decreasing the length of the forward steps, it actually fills the plane. There are different constructions known, the one shown here fills a square tilted by :
peano := plot::Lsys(PI/2, "F", "F" = "F+F-F-F-F+F+F+F-F"):
The transformation rule says to replace each straight line with the following construction:
peano::Generations := 1: plot(peano)
After a few iterations, the lines already get very close to one another:
peano::Generations := 5: plot(peano)
Many L-systems contain different types of lines: While they are drawn exactly the same, their transformation rules are different from one another. The following example shows an image similar to the Sierpinski triangle:
l := plot::Lsys(PI/3, "R", "L" = "R+L+R", "R" = "L-R-L", "L" = Line, "R" = Line, Generations = 7): plot(l)
The Push and Pop operations can be used to draw "arms" in an L-system:
plot(plot::Lsys(23*PI/180, "F", "F" = "FF-[-F+F+F]+[+F-F-F]", Generations = 4))
L-systems have been used to simulate plant growth. We show an example here that uses the symbols B, H, and G to change the color of lines:
l := plot::Lsys(PI/9, "BL", "L" = "BR[+HL]BR[-GL]+HL", "R" = "RR", "L" = Line, "R" = Line, "B" = RGB::Brown, "H" = RGB::ForestGreen, "G" = RGB::SpringGreen, Generations = 6): plot(l)
The attribute Generations can be animated. This way, we can actually make the "plant" "grow:"
plot(plot::Lsys(a*PI/45, "BL", "L" = "BR[+HL]BR[-GL]+HL", "R" = "RR", "L" = Line, "R" = Line, "B" = RGB::Brown, "H" = RGB::ForestGreen, "G" = RGB::SpringGreen, Generations = a, a = 1 .. 6)):
L-systems can display a couple of popular fractals. One example is the Koch snowflake, generated by replacing each straight line with a straight line, followed by a left turn of , another straight line, a right turn of , another straight line, another left turn of and a final straight line:
koch := plot::Lsys(PI/3, "F--F--F", "F" = "F+F--F+F"):
The starting rule has been chosen to be an equilateral triangle:
koch::Generations := 0: plot(koch)
The first generation looks like this:
koch::Generations := 1: plot(koch)
The limit is pretty well approximated after five generations:
koch::Generations := 5: plot(koch)
Finally, we use plot::modify and the "StepLength" slot to show the first couple of iterations superimposed on one another:
colors := [RGB::Red, RGB::Green, RGB::Blue, RGB::Yellow, RGB::DimGrey]: plot(plot::modify(koch, Generations = i, StepLength = 3^(-i), LineColor = colors[i+1]) $ i = 0..4)
Another well-known example of a fractal generated by an L-system is Heighway's Dragon curve. Informally, it is generated by "drawing a right angle and then replacing each right angle by a smaller right angle" (Gardner). It has been used in the book "Jurassic Park" by Michael Crichton and thereby got another nickname, the "Jurassic Park fractal:"
plot(plot::Lsys(PI/2, "L", "L" = "L+R+", "R" = "-L-R", "L" = Line, "R" = Line, Generations = 9))
It is interesting to note that the iteration rules of this curve are equivalent to appending a mirrored copy of the curve to its end:
plot(plot::Lsys(PI/2, "L", "L" = "L+R+", "R" = "-L-R", "L" = Line, "R" = Line, Generations = a, a = 1..9))
While the L-system of the previous example corresponds to the definition found in the literature, the images in at least one popular source show another system (while the definition given is the one from above), namely:
plot(plot::Lsys(PI/4, "X-F-Y", "X" = "X+F+Y", "Y" = "X-F-Y", "X" = Line, "Y" = Line, Generations = 9)):
An L-system may contain letters that are not meant to show in the final graphic, so they form some sort of "markers" for subsequent iteations. For this purpose, you may use the turtle rule Noop:
plot(plot::Lsys(PI/12, "X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X", "X" = "[F+F+F+F[---X-Y]+++++F++++++++F-F-F-F]", "Y" = "[F+F+F+F[---Y]+++++F++++++++F-F-F-F]", "X" = Noop, "Y" = Noop, Generations = 3))
plot(plot::Lsys(PI/2, "FB", "A" = "FBFA+HFA+FB-FA", "B" = "FB+FA-FB-JFBFA", "F" = "", "H" = "-", "J" = "+", "A" = Noop, "B" = Noop, "H" = Noop, "J" = Noop))
Using this rule, we can use the following formulation of the popular Hilbert curve due to Ken Philip:
plot(plot::Lsys(PI/2, "x", "x" = "-yF+xFx+Fy-", "y" = "+xF-yFy-Fx+", "x" = Noop, "y" = Noop))
To animate the creation process of the Hilbert curve, we adjust the length of the lines to the current number of iteration steps:
plot(plot::Lsys(PI/2, "x", "x" = "-yF+xFx+Fy-", "y" = "+xF-yFy-Fx+", "x" = Noop, "y" = Noop, Generations = i, StepLength = 1/(2^i-1), i = 1..6, Frames = 6))
In some cases, systems will need small angles and long strings in order to specify the desired directions. Take for example the following system:
plot(plot::Lsys(7*PI/15, "F", "F"="F+F--F+F", Generations=4))
The rotations to the right use an angle of , while that to the left (the sharp spike) is a turn of . It would look more natural, however, to have the turtle start to the right, i.e., at an angle of . Since no multiple of is equal to modulo 2 π, this requires that we use a smaller angle, adjusting our iteration rule:
plot(plot::Lsys(7*PI/30,"+++++++++++++++F", "F"="F++F----F++F", Generations=4))
alpha |
Angle (in radians) for turning commands. Animatable. alpha is equivalent to the attribute RotationAngle. |
start |
String used as the starting rule. start is equivalent to the attribute StartRule. |
trans, … |
Iteration and Turtle command rules (see below). trans, … is equivalent to the attributes IterationRules, TurtleRules. |
a |
Animation parameter, specified as a = a_{min}..a_{max}, where a_{min} is the initial parameter value, and a_{max} is the final parameter value. |