This lab focuses on recursion, that is the topics we discussed this week. In particular the drawing examples and code will be most relevant.
We will be drawing a Koch Curve by writing a recursive function draw_koch(length, generation)
. The Koch curve is a fractal, a shape that is self-similar, i.e., it can be decomposed into smaller versions of the same shape.
Many of the techniques that we use to generate fractals computationally rely on the repetition of a set of steps, so we tend to talk about generations, which are the number of iterations that we used to produce the drawing. The Koch curve is a fairly simple one, and we can see its structure most clearly by looking at how it changes from one generation to the next.
The starting place (generation 0) is a straight line.
For the first generation, we cut the line into thirds and replace the middle segment with two segments of the same length, forming two sides of an equilateral triangle.
The second generation is formed by applying this same process to every line in generation 1.
Further generations are formed by repeating this process, taking each line, breaking it into thirds and replacing the middle segment with a bump. Conceptually, if you take this out to infinity, you will have a very curious mathematical phenomenon – an infinitely long line between two fixed points a finite distance apart that also occupies a finite area. In practice, however, when the length of the individual lines becomes 1 pixel long, that is pretty much as small as we can draw.
To actually draw the shape we won’t draw a line and then go back and remove a piece. Instead, we start conceptually with the highest generation of the fractal first. If you think about a generation 2 curve, it is really made up of four generation 1 curves that are each 1/3 the length of the generation 2 curve. But each of those generation 1 curves are made up of generation 0 curves 1/3 of that length. What that means is that we don’t actually draw any of the higher generation curves, the only thing we draw is a whole bunch of generation 0 curves (straight lines!) in different locations.
Specify the function definition: draw_koch(length, generation)
Specify the recursive relationship
As noted above, a generation 2 curve is made up four generation 1 curves each 1/3 of the length of the generation 2 curve. Thus we can define a Koch curve of length l and generation n as 4 Koch curves of length l/3 and generation n-1.
Let’s assume we start at the left terminus of the curve, facing right. If we look at the generation 1 curve example above, we see that move forward l/3, turn left 60 degrees (to draw the “bump”), move forward l/3, turn right 120 degrees, move forward l/3, turn left 60 degrees, and draw a final line of length l/3. In our recursive case, we wont draw lines, we will draw smaller Koch curves, but the turns between curves will be the same
Specify the base case
As specified above, the base case, generation 0, is just a straight line of length
Put it all together. Show a possible implementation and check out the complete program.
def draw_koch(length, generations):
"""Draw a Koch curve
Args:
length: Distance bewteen starting and ending points
generations: Number of generations to draw
"""
if generations == 0:
forward(length)
else:
draw_koch(length / 3, generations - 1)
left(60)
draw_koch(length / 3, generations - 1)
right(120)
draw_koch(length / 3, generations - 1)
left(60)
draw_koch(length / 3, generations - 1)