L Systems
L Systems
To see the full turtle sequence being generated by an L-System open up an HScript Textport (alt+shift+t)
And type:
opinfo /pathto/L-System
You can drag the L-System node into the textport to get the path automatically.
Turtle sequence
The basic L-system commands are used to draw a line or series of lines. Each command follows on from the
last, so as to draw a line through space. It helps to imagine a point (or turtle) moving forwards, and rotating left,
right, pitching up and down, and rolling about its axis.
F(l,w,s,d For each of the above commands (l,s,w,d) assigns * Roll 180 degrees
) distance l of width w using s cross sections of d
f(l,w,s,d) divisions each. ~ Pitch / Roll / Turn random amount up to a degrees.
etc Default 180.
Not all of these values need to be set eg. $(x,y Rotates the turtle so the up vector is (0,1,0). Points
,z) the turtle in the direction of the point (x,y,z). Default
F(l) creates a line of distance (length) l behavior is only to orient and not to change the
direction.
F(l,w) Creates a line of distance l and width w
Without further information these commands use the
Value ‘Angle’ to determine the angle rotated in each turn
# Increment color index V by UV Increment's second t Initially 0. After that it is set to the iteration count.
parameter.
x, y, z The current turtle position in space.
Appending (s) can be used to override the step
size/thickness/angle etc. A The arc length from the root of the tree to the
current point.
J Copy geometry from leaf input J, K, or M at the T The LSystem gravity parameter.
K turtle’s position
M U The color map U value.
J(s,x,a,b,c) The geometry is scaled by the s parameter V The color map V value.
etc (default Step Size) and stamped with the
values a through c (default no stamping). W The current width at the current point.
Stamping occurs if the given parameter is
present and the relevant Leaf parameter is set.
The x parameter is not used and should be set
to 0. Behavioural Commands
{ Start a polygon % Cut off remainder of branch
In the first example, only an initial premise string is used, consisting of F+-
and [ ]
Premise FF[+F-F+F]F-F[F-F-F]+F[+FF-F[+F+F]F-F-F]F[-F[+F+F-F-F]F-F]
angle 90
I have coloured the lines to show the main trunk, branches and nested
branches. If I remove the branches is square brackets we are left with the
simple instructions for the main trunk FFF-F+FF
Edge Rewrite
Each edge F is replaced by a new sequence. Here it is replaced by a line with a triangular detour which is
drawn by the turtle sequence F+F--F+F
Every generation all the Fs are replaced again.
Premise F
Rule 1 F=F+F--F+F
angle 60
Rule 1 F(i)=F(i/3)+F(i/3)--F(i/3)
+F(i/3)
angle 60
And here a different sequence FF++F++F+F++F-F inserts a diamond shape:
Premise F
Rule 1 F=FF++F++F+F++F-F
angle 60
Premise FA
Rule 1 A=+H--H+A
angle 60
In the second example a node A is inserted at the end of the first F line (FA). In the second generation A is
inserted (to allow further iterations of the sequence) then the point turns 30 degrees, then a branch containing
a half line is drawn, and the drawing point jumps back to just after the 30 degree turn.
Premise FA
Rule 1 A=A-[H]
angle 30
This example is a slightly simplified version of the Houdini default L-System settings. I have coloured each
generation with a different colour to make it clearer how the tree grows.
This tree uses two rules, but it is pretty
straightforward. Rule 1 establishes the
branches. Rule 2 uses the B character to
insert a rotated line at each branch.
Premise FFFA
Rule 1 A=[B]////[B]////[B]
Rule 2 B=&FFFA
angle 28
Branching Structures
from The Algorithmic Beauty of Plants p25. Also available as defaults ‘2D Plants’ in Houdini
Figure 1.24: Examples of plant-like structures generated by bracketed OLsystems. L-systems (a), (b) and (c)
are edge-rewriting, while (d), (e) and (f) are node-rewriting.
a b c
Generations: 4 Generations: 5 Generations: 4
Premise: F Premise: F Premise: F
Rule1: F=F[+F]F[-F]F Rule1: F=F[+F]F[-F]F Rule1: F=F[+F]F[-F]F
Angle:25 Angle:20 Angle:20
d e f
Generations: 6 Generations: 6 Generations: 6
Premise: X Premise: X Premise: X
Rule1:F =F[+F]F[-F]F Rule1:X =F[+X][-X]FX Rule1:X =F-[[X]+X]+F[+FX]-X
Rule2: F=FF Rule2: F=FF Rule2: F=FF
Angle:22.5 Angle:35 Angle:22.5
Symbol variables
You may have noticed that many of the turtle symbols have one or more optional variables after them. Usually
they have a default value which can be edited in the ‘Values’ menu, or this can be inserted manually into the
sequence and can be manipulated using simple maths. This gives us more control over the way the system
changes over the generations.
", _ (s) override step size Step Size Scale. Use to override default scale
scale
;, @ (a) override angle scale Angle Scale. Use to override default scale
Examples
Step Size = 0.2 Step Size = 0.2 Step Size = 0.2 Step Size = 0.2 Step Size = 0.2
Angle = 30 Angle = 30 Angle = 60 Angle = 60 Angle = 30
Premise: FA Premise: F(0.1)A Premise: FA Premise: FA Premise: FA
Rule1: A=A/[+FBJ] Rule1: A=A/[+FBJ] Rule1: A=A/[+FBJ] Rule1: A=A/(30)[+FBJ] Rule1: A=A/[+FBJ(0.1)]
Uses Step Size & Angle The first F uses the Changing the angle But setting the roll value Here we override the
from the values menu given value of 0.1 value changes both roll in the rule keeps the input sphere geometry
and turn (/ and +) spacing between size (J) so it no longer
branches constant, uses step size. (see
while still changing the “Input Geometry in
Angle L-Systems” below)
To set up a variable to change with each generation, you have to declare a value for it in the premise, then use
a variable to represent this on both sides of the rule, and when a node or edge is declared for rewriting,
manipulate this value (ie. add, multiply, divide a constant from it) This will be iterated every time the edge or
node is replaced.
The effect achieved is similar to using the scale values ", _,!, ?,;, @ but with greater control
Premise A(1)
Rule A(i)= F(i)A(i*0.5)
This way i is scaled before A is re-evaluated. The important part is the premise: you need to
start with a value to be able to scale it.
Premise FFFA(1)
Rule 1 A(i)=[&F(i)A(i*0.5)]////[&F(i)A(i*0.5)]
angle 45
generations 6
Monopodial Tree
The Algorithmic Beauty of Plants p.56, figure 2.6, also shown by the Houdini preset "Monopodial Tree"
Custom Values
Premise A(1,10)
b = contraction ratio trunk
Rule 1 A(l,w)=F(l,w)[&(c)B(l*e,w*h)]/(m)A(l*b,w*h) e = contraction ratio branches
c = branching angle trunk
Rule 2 B(l,w)=F(l,w)[-(d)$C(l*e,w*h)]C(l*b,w*h) d = branching angle lateral axes
h = width decrease rate
Rule 3 C(l,w)=F(l,w)[+(d)$B(l*e,w*h)]B(l*b,w*h)
i = divergence angle
For each tree below the rules are the same, only the values are changed.
Sympodial Tree
The Algorithmic Beauty of Plants p.59, figure 2.7, also shown by the Houdini preset "Sympodial Tree"
Custom Values
Premise A(1,10)
b = contraction ratio 1
Rule 1 A(l,w)=F(l,w)[&(c)B(l*b,w*h)]//(180)[&(d)B(l*e,w*h) e = contraction ratio 2
c = branching angle 1
Rule 2 B(l,w)=F(l,w)[+(c)$B(l*b,w*h)][-(d)$B(l*e,w*h)] d = branching angle 2
h = width decrease rate
For each tree below the rules are the same, only the values are changed.
Premise= FA Premise= FA
Rule 1= A =T"[&FA]////[&FA] Rule 1= A=T" [&FA]////[&FA]
Angle= 45 Angle= 45
Step Size Scale= 0 .6 Step Size Scale= 0 .6
Generations= 10 Generations= 10
Gravity= 0 0
Gravity= 2
Premise= FA Premise= FA
Rule 1= A =T"[&FA]////[&FA] Rule 1= A="[&TFA]////[&FA]
Angle= 45 Angle= 45
Step Size Scale= 0 .6 Step Size Scale= 0 .6
Generations= 10 Generations= 10
Gravity= 50 0
Gravity= 2
Ternary Tree
The Algorithmic Beauty of Plants p.60, figure 2.8, also shown by the Houdini preset "Ternary Tree"
Custom Values
Premise F(0.5,1)A
b = divergence angle 1
Rule 1 A=TF(0.5,1)[&(c)F(0.5,1)A]/(b)[&(c)F(0.5,1)A]/(e)[& e = divergence angle 2
(c)F(0.5,1)A] c = branching angle
d = elongation rate
Rule 2 F(l,w)=F(l*d,w*h) h = width increase rate
T = tropism (gravity)
For each tree below the rules are the same, only the values are changed. The exception is the final tree which
is grown at an angle using the initial premise +(75)F(0.5,1)A. This allows T to pull the tree to one side instead
of directly downwards. It is then rotated back into an upright position using a transform node.
Premise FFFA
Rule 1 A=!"[&&J][B]////[&&J][B]////[&&J]B
Rule 2 B=&FFFAK
angle 28
J K
Premise A
Rule 1 A=X+[A+]−−////[−−J]X[++J]−[A]++AK
Rule 2 X=FY[//&&J]FY
Rule 3 Y=YFY
angle 18
Generations 5
Stamping Geometry
You can use the stamp expression to influence the inputs to an L-System. The syntax to use is
stamp("/path/to/lsystem", "lsys",0)
The “lsys” variable can be changed inside the l-system using the parameters after the J, K or M symbols
J(s,x,a,b,c) etc The geometry is scaled by the s parameter (default Step Size) and stamped with
the values a through c (default no stamping). Stamping occurs if the given
parameter is present and the relevant Leaf parameter is set. The x parameter is not
used and should be set to 0.
Premise FA
Rule 1 A=AF//[+&B]//[&B]//[&B]
angle 48
Generations 21
Example using stamp expression to change colour
In this example we only have one geometry model, and we use stamping to change the colour.
R: 0.5+stamp("../lsystem1","lsys",0)/20
G: 0.7
B: 1
The l-system is very similar to above, except that the J third character
value is simply ‘t’ which is tweaked in the colour node to give an output
between 0 and 1, and the first (scaling) character of J also uses ‘t’ to
make the petals smaller as they ascend.
Premise FA
Rule 1 A=A"!F//[+&B]
Rule 2 B=J(0.5+t/10,0,t)
angle 48
Generations 21
Probability
Appending a colon followed by a fraction to the end of a rule determines how often that rule is applied
Eg. B=&FFFAK:0.75 would replace B with &FFFAK only ¾ of the time. This is a good way to introduce more
natural looking dropoup to L-Systems.
This is a copy of the default L-System with
geometry leaves and berries, only this time the
second rule only executes in 75% of cases
(:0.75)
This gives a much more natural appearance.
Note that more than 25% of the foliage is
missing because some branches drop out
earlier on eliminating everything above them.
Premise FFFA
Rule 1 A=!"[&&J][B]////[&&J][B]////[&&J]B
Rule 2 B=&FFFAK:0.75
angle 28
Rule 2 B=&FFFAK:0.45
Rule 3 B=&FFFAM:0.25
Changing ‘seed’ in the geometry menu will give a different random dropout
Premise F
Rule 1 F=F[-F]F[+F]F:0.33
Rule 2 F=F[-F]F:0.33
Rule 3 F=F[+F]F:0.33
angle 28
Generations 6
Conditionals
We can add a condition to an L_Systems rule so that it only executes when the condition is true.
The symbol for a conditional is a colon : after which the condition is given. For example
A:t<4=J
This would replace A with geometry input J only for the first 4 iterations
Rule 1 A:t>1=AF[+J][-J]
Rule 2 A:t==1=AH[J]
angle 60
Conditional Edge Rewrite Examples from The Algorithmic Beauty of Plants p9 - p11.
Dragon_curve Sierpinski_gasket
Generations: 12 Generations: 8
Premise: l Premise: r
Rule1: l:t<b=l+r+ Rule1: l:t<b=r+l+r
Rule2: r:t<b=-l-r Rule2: r:t<b=l-r-l
Rule1: l=F Rule1: l=F
Rule1: r=F Rule1: r=F
Angle:90 Angle:60
Variable b: ch("generations") (ie. 12) Variable b: ch("generations") (ie. 8)
Bringing together Geometry Inputs, Custom Variables and Conditionals
J(,,0)
J(,,1)
K(,,0)
K(,,1)
K(,,2)
Premise A(7)
Rule 1 A(i):i==7=FI(20)[&(60)∼J(0)]/(90)[&(45)A(0)]/(90)[&(60)∼J(0)]/(90)[&(45)A(4)]FI(10)∼K(0,0,0)
Rule 2 A(i):i<7=A(i+1)
Rule 3 I(i):i>0=FFI(i-1)
Rule 4 J(i)=J(i+1,0,(i+1)/t)
Rule 5 K(i)=K(i+1,0,(i+1)/15)
Generations 40
This can be used in Houdini if the option “Context includes Siblings” is turned on.
Note that the > and < signs don’t mean “greater than” or “less than”, they mean “comes after” or “comes
before”.
Example of Context sensitive leaf drawing
In this example, there are two conditions for drawing leaf geometry (J)
If B comes after A and before A, a leaf is drawn to the left
If A comes after B and before A, a leaf is drawn to the right
All As and Bs then become left or right angles lines
Premise BABAABBA
Rule 1 A<B<A=[---J] B
Rule 2 B<A<B=[+++J] A
Rule 3 A=-F
Rule 4 B=+F
angle 20
Generations 5
The result of these rules is that leaves are only drawn when the
direction changes and are always situated on outside curves.
Examples of branching structures generated using L-systems based on the results of Hogeweg and Hesper
The Algorithmic Beauty of Plants p.34
Sunflower
The sunflower uses a single rule to draw the seeds and petals. The only change is that the seeds become
petals as the generations increase, which is done using Conditionals
Premise A(0)
J
Rule 1 A(n) = +(137.5)["f(n^0.5)C(n)]A(n+1)
Generations 625
M(,,3)
The same principle can be used to create flowerheads. In this flower the angle and size of the petals is
increased as they get further from the centre (as n becomes greater)
Premise A(0)
Rule 2 C(n)=&(n*-180/b)J(0.5+(b-n)/b)
Step Size 1
Variable b ch("generations")
Generations 90
Creating Leaves from Surface Geometry
It is possible to use L-Systems to draw polygon surfaces, using the following commands:
{ Start a polygon
. Make a polygon vertex
} End a polygon
The Algorithmic Beauty of Plants contains several examples of surfaces built from polygons, and one of these
is integrated into the houdini L-System examples as ‘Cordate Leaf’
Cordate Leaf
The Algorithmic Beauty of Plants p.123, Figure 5.5
This is created by drawing polygon triangles and joining them up to form the shape of a leaf.
If we look at the turtle generated for each generation we can see that the rules add progressively longer lines
(lists of FFF), and join these up with progressively wider angles (lists of +++)
The results below show only the right side for simplicity ie. they ignore rule 2
Premise [A][B]
Rule 1 A=[+A{.].C.}
Gen 0 [A]
Rule 2 B=[-B{.].C.} Gen 1 [[+A{.].C.}]
Gen 2 [[+[+A{.].C.}{.].FFFC.}]
Rule 3 C=FFFC
Gen 3 [[+[+[+A{.].C.}{.].FFFC.}{.].FFFFFFC.}]
Angle 16 Gen4 [[+[+[+[+A{.].C.}{.].FFFC.}{.].FFFFFFC.}{.].FFFFFFFFFC.}]
Angle 60
generations 20
b= 5 b= 5 b= 5 b= 5 b= 5 b= 5
c=1 c=1 c=1 c = 1.2 c = 1.2 c = 1.1
d=1 d=1 d = 0.6 d = 10 d=4 d=1
e=1 e=1 e = 1.06 e=1 e = 1.1 e = 1.2
f=0 f=1 f = 0.25 f = 0.5 f = 0.25 f=1
A Rose Leaf
From The Algorithmic Beauty of Plants p.126, Figure 5.8
Premise [{A(0).}][{C(0).}]
Rule 1 A(i) =
.F(b,c).[+B(i)F(f,h,i).}][+B(i){.]A(i+1
)
Rule 2 C(i) =
.F(b,c).[-B(i)F(f,h,i).}][-B(i){.]C(i+1)
Angle 45
Angle 45