An L-system (Lindenmayer system) builds branching structures in two stages: first, a set of rewrite rules expands a short starting string into a much longer one; then, a turtle interpreter reads the result as drawing commands: move forward, turn left or right, save position, restore position. The combination of string rewriting and stack-based turtle graphics is what makes L-systems so effective at producing plant-like branching patterns from compact grammars. The Procedural Plants and Trees hub includes an interactive L-system visualization where you can edit the grammar and watch the turtle draw the result command by command.
How Rewrite Rules Work
An L-system grammar has two parts:
- Axiom: the initial string of symbols, such as
ForX. - Production rules: one or more replacements of the form symbol → string. Each rule tells the system: whenever you see this symbol, replace it with this string.
The rewrite process applies every rule simultaneously to every matching symbol in the current string, producing a new string for the next iteration. This is called parallel rewriting: each symbol is replaced in one pass, not sequentially.
| Term | Meaning | Example |
|---|---|---|
| Axiom | Starting string | F |
| Production rule | Symbol → replacement | F → F[+F]F[-F]F |
| Iteration | One full pass of parallel replacement | After one rewrite, F becomes F[+F]F[-F]F |
| Constant | Symbol with no rule; it stays as itself | +, -, [, ] are never replaced |
Symbols that have no matching production rule are called constants: they pass through unchanged. This is how L-systems keep the structural commands (+, -, [, ]) intact while only expanding the drawable symbols.
Example: The Classic Branching Rule
Start with axiom F and one rule:
F → F[+F]F[-F]F
After each iteration:
| Iteration | String (abbreviated) | Symbols |
|---|---|---|
| 0 | F | 1 |
| 1 | F[+F]F[-F]F | 9 |
| 2 | F[+F]F[-F]F[+F[+F]F[-F]F]F[+F]F[-F]F[-F[+F]F[-F]F]F[+F]F[-F]F | 73 |
| 3 | (much longer) | 585 |
The string grows roughly by a factor of 9 each iteration because every F is replaced by a 9-symbol string. This exponential growth is characteristic of L-systems and is why even a single production rule can produce a detailed branching skeleton in just a few iterations.
Turtle Commands: Drawing the String
Once the rewrite stage produces a string, a virtual turtle interprets it as drawing instructions. The turtle has a position (x, y), a heading direction (angle), and a stack that saves and restores state.
| Command | Name | Turtle Action |
|---|---|---|
F | Draw forward | Move one step in the current direction, drawing a line segment. |
+ | Turn left | Rotate the heading counterclockwise by the turn angle (e.g., 22°). |
- | Turn right | Rotate the heading clockwise by the turn angle. |
[ | Save (push) | Record the current position and heading onto the stack. The turtle stays in place. |
] | Restore (pop) | Pop the most recent saved position and heading from the stack. The turtle jumps back to that saved state. |
The [ and ] commands are what create branching. When the turtle encounters [, it marks a fork point. After drawing one branch, ] returns the turtle to the fork point, ready to draw the next branch in a different direction.
Rewrite & Turtle Stack
The split view above connects the grammar to the geometry. On the left, the grammar editor shows the axiom and production rules. The Iteration slider steps through rewrite generations so you can watch the string expand from a single symbol into a branching program. On the right, the turtle viewport draws the result. Use the transport controls to step through commands one at a time: each F draws a segment, each [ pushes the current state onto the stack shown in the panel below, and each ] pops the stack and returns the turtle to the saved position.
Try changing the turn angle and watch how the branch spread changes without altering the grammar. Then edit the axiom or rules to explore how different productions produce different structures.
Step-by-Step Walkthrough
Here is how the turtle processes the string F[+F]F[-F]F with a turn angle of 22° and a step of one unit, starting at position (0, 0) heading upward (90°):
| # | Command | Action | Position | Heading | Stack |
|---|---|---|---|---|---|
| 1 | F | Draw a segment upward | (0, 1) | 90° | [] |
| 2 | [ | Save current state | (0, 1) | 90° | [(0, 1, 90°)] |
| 3 | + | Turn left 22° | (0, 1) | 112° | [(0, 1, 90°)] |
| 4 | F | Draw segment at 112° | (cos 22°, 1 + sin 22°) | 112° | [(0, 1, 90°)] |
| 5 | ] | Restore saved state | (0, 1) | 90° | [] |
| 6 | F | Draw a segment upward | (0, 2) | 90° | [] |
| 7 | [ | Save current state | (0, 2) | 90° | [(0, 2, 90°)] |
| 8 | - | Turn right 22° | (0, 2) | 68° | [(0, 2, 90°)] |
| 9 | F | Draw segment at 68° | (sin 22°, 2 + cos 22°) | 68° | [(0, 2, 90°)] |
| 10 | ] | Restore saved state | (0, 2) | 90° | [] |
| 11 | F | Draw a segment upward | (0, 3) | 90° | [] |
The result is a main trunk with two side branches: one angling left at the first segment, one angling right at the second segment. The trunk continues straight through both branch points because each ] restores the original heading.
Putting It Together
The complete L-system pipeline for a tree:
- Define the grammar: choose an axiom (such as
F) and one or more production rules (such asF → F[+F]F[-F]F). - Iterate the rewrite: apply the rules in parallel for a chosen number of iterations. More iterations produce a longer, more detailed string.
- Interpret with the turtle: feed the final string into the turtle interpreter. Each
Fdraws a segment,+/-change direction, and[/]manage the branching stack. - Render the result: the accumulated line segments form the branching tree skeleton.
The turn angle and step size are not part of the grammar; they are parameters of the turtle interpreter. This means the same grammar can produce dramatically different shapes by changing only the angle. A narrow angle (10–15°) produces a compact, upright tree; a wider angle (30–40°) produces a spreading, open crown.
Beyond the Basic Grammar
The simple F → F[+F]F[-F]F rule is just one example. Real L-system grammars can include:
- Multiple rules for different symbols, such as separate rules for trunk (
T), limb (L), and leaf (G) symbols, each producing different branching behavior. - Multiple rules for the same symbol (stochastic L-systems), where each rule has a probability so the same grammar generates varied trees.
- Parametric symbols that carry numeric values, such as
F(length, thickness), so segment properties depend on depth, resource state, or environmental conditions.
For the full interactive tutorial, including a live grammar editor, visual rewrite history, and step-through turtle animation, see the complete Procedural Plants and Trees hub. The interactive L-system visualization there lets you edit the axiom, rules, and turn angle, then watch the string expand and the turtle draw the result command by command.