Hilbert Curve¶
By the end of this lab you'll be able to:
- Implement a space-filling curve using two mutually recursive functions
- Understand what "space-filling" means — a curve that visits every point in a region
- See how two functions can call each other back and forth (mutual recursion)
A continuous curve that fills an entire square region without crossing itself. At depth 5, the Hilbert Curve visits 4^5 = 1024 tiny squares — leaving no gaps.
Welcome to the Hilbert Curve!
David Hilbert discovered this space-filling curve in 1891. It's used today
in database indexing, image processing, and fractal antennas!
Let's code it together!
How It Works¶
Two functions — hilbert_a() and hilbert_b() — each produce one "U" shape. They call each other to fill the space recursively:
hilbert_a(n): turn left, call B, forward, call A, turn right, forward, call A, turn left, forward, call B, turn righthilbert_b(n): turn right, call A, forward, call B, turn left, forward, call B, turn right, forward, call A, turn left
The n parameter controls depth — at depth 0, only forward() is drawn, no turns. This prevents infinite recursion.
Sample Code¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | |
What Do You Think Will Happen?
A "space-filling" curve visits every point in a region.
Will the curve look like a grid of U-shapes, or like a single winding path?
Make your guess — then click Run to find out!
Try It Now¶
A single winding path that fills the square — every cell visited exactly once, never crossing itself. Were you right?
How It Works¶
hilbert_a and hilbert_b call each other — this is mutual recursion. Each function produces a U-shape oriented differently, and together they fill the whole square.
At depth n, the curve has 4^n segments. At depth 5, that's 4^5 = 1024 tiny squares visited.
Explanation Table¶
| Line | What it does |
|---|---|
if n == 0: return |
Base case — stop recursing |
hilbert_a calls hilbert_b |
Mutual recursion — each function needs the other |
monty.left(90) / right(90) |
Orientation turns between U-shapes |
monty.forward(step) |
Connect adjacent U-shapes |
step = 6 |
Size of each unit segment |
Learning Check¶
Your Turn — Try Depth 3
Change hilbert_a(5) to hilbert_a(3). How many cells will be visited?
(4^3 = ?). Predict, then run it to see the simpler structure clearly.
Depth 3 with step = 40 makes each U-shape large enough to see clearly — you can trace the path from one end to the other.
Experiments¶
-
Change the color. Try
pencolor('crimson'). You'll know it worked when the curve turns red. -
Add color by step. Use a counter variable and
pencolor(colors[counter % len(colors)])inside the step. You'll know it worked when the curve is multicolored. -
Try depth 4. Change back to
step = 12andhilbert_a(4). You'll know it worked when you see a denser grid-filling pattern. -
Draw only hilbert_b. Call
hilbert_b(4)instead ofhilbert_a(4). You'll know it worked when you see a slightly different orientation of the same space-filling curve.
Space Filled!
You used mutual recursion — two functions calling each other — to build
one of the most famous curves in mathematics. It's used in real GPS systems!
Up next: Cantor Dust — a fractal made of gaps instead of lines.