Recursion, self-similarity, the Cantor set, Koch curve, fractal trees, and L-systems — the geometry of nature.
Look outside. Trees, coastlines, blood vessels, lightning, cauliflower — none of these are circles, rectangles, or lines. Euclidean geometry can't describe them. We need fractal geometry.
Benoit Mandelbrot coined the term "fractal" in 1975, defining it as "a rough or fragmented geometric shape that can be split into parts, each of which is (at least approximately) a reduced-size copy of the whole."
Two types of fractals: deterministic (perfectly self-similar, like the Koch curve) and stochastic (statistically self-similar, like a real tree or a stock chart).
Recursion is the engine behind fractals: a function that calls itself. Consider factorial:
pseudocode function factorial(n): if n == 1: return 1 return n * factorial(n - 1) # factorial(4) = 4 * 3 * 2 * 1 = 24
Recursion is powerful for graphics because a function can call itself more than once. One call becomes two, two become four, four become eight — a branching explosion of self-similar structure.
pseudocode function drawCircle(x, y, r): ellipse(x, y, r, r) if r > 2: drawCircle(x + r/2, y, r/2) # right drawCircle(x - r/2, y, r/2) # left
In 1883, George Cantor created one of the first fractals with a simple rule: take a line, erase the middle third, and repeat on the remaining segments.
pseudocode function cantor(x, y, len): if len < 1: return # Exit condition line(x, y, x + len, y) y += 20 cantor(x, y, len / 3) # Left third cantor(x + len * 2/3, y, len / 3) # Right third
Helge von Koch (1904) created a curve by replacing the middle third of each line segment with two sides of an equilateral triangle. After many iterations, it forms an infinitely jagged, infinitely long line that fits in a finite space.
The implementation uses an ArrayList technique: instead of recursive function calls, we store line segments as objects and iteratively replace each one with four new segments. This lets us treat each segment independently — useful for animation and physics.
A branch is a line with two branches connected to its end. This recursive definition gives us a tree.
pseudocode function branch(len): line(0, 0, 0, -len) # Draw upward translate(0, -len) # Move to tip len *= 0.66 # Shrink if len > 2: save() rotate(theta) branch(len) # Right branch restore() save() rotate(-theta) branch(len) # Left branch restore()
Deterministic trees are perfectly symmetrical. Real trees are not. By adding randomness, we get organic, natural-looking results.
Two approaches: (1) vary the branching angle randomly for each branch; (2) vary the number of sub-branches randomly (1 to 4 instead of always 2).
pseudocode function branch(len): line(0, 0, 0, -len) translate(0, -len) if len > 2: n = random(1, 4) # Random number of branches for i in n: theta = random(-PI/2, PI/2) # Random angle save() rotate(theta) branch(len * 0.66) restore()
In 1968, botanist Aristid Lindenmayer created a grammar-based system to model plant growth. An L-system has three components:
| Component | Description | Example |
|---|---|---|
| Alphabet | Valid characters | F, G, +, -, [, ] |
| Axiom | Initial sentence | "F" |
| Rules | Replacement rules | F → FF+[+F-F-F]-[-F+F+F] |
Each generation, every character in the sentence is replaced according to the rules. The sentence grows exponentially.
An L-system sentence is meaningless until we interpret it as drawing commands. The standard mapping:
| Character | Action |
|---|---|
| F | Draw a line forward, then move forward |
| G | Move forward without drawing |
| + | Turn right by angle θ |
| - | Turn left by angle θ |
| [ | Save current position and angle (push) |
| ] | Restore saved position and angle (pop) |
With this system, the rule F → FF+[+F-F-F]-[-F+F+F] generates a beautiful, plant-like structure after just 4-5 generations.
Below is an interactive fractal tree. Move the slider to change the branching angle and watch the tree reshape itself in real time.
Adjust the angle slider. Click "Randomize" for a stochastic tree with varied angles and branch counts.
| Topic | Key Takeaway |
|---|---|
| Fractals | Self-similar patterns that repeat at every scale |
| Recursion | A function that calls itself, with an exit condition |
| Cantor set | Erase the middle third, repeat |
| Koch curve | Replace middle third with a triangle bump, repeat |
| Fractal tree | A branch is a line with two branches at its end |
| Stochastic | Add randomness for organic, natural patterns |
| L-systems | Grammar-based fractals: alphabet, axiom, rules |
| Turtle graphics | Interpret L-system sentences as drawing commands |
What we covered:
• Self-similarity and fractal dimension
• Recursion with exit conditions
• Cantor set, Koch curve
• Deterministic and stochastic trees
• L-systems and turtle graphics
What comes next:
Chapter 9: The Evolution of Code. Genetic algorithms, fitness functions, selection, crossover, and mutation. We let our objects evolve and discover solutions we never could have designed by hand.