In the previous section, we didn't give the specifics of exactly how we generated the Koch curve of level 5 which we showed. The general procedure was pointed out (``Begin with F. Replace each F with FLFRRFLF. Repeat 5 times.''), but if you actually tried to do it yourself, you might have found it a bit tricky. Since the turtle command for the curve has 2388 letters, certainly it isn't something you would expect someone to type in directly.
Instead, a small maple procedure was written to generate it. Before giving
the details, let's analyze the process a bit. We shall rely heavily on the
self-similar nature of the Koch curve
.
Notice that the curve
is made up of four small copies of
itself, arranged as
The second definition is much simpler to implement in a programming language which allows recursive functions, such as maple.4.5 To see this, let's implement the factorial function in both ways:
> fact1 := proc(n::posint)
local i,ans;
ans := 1;
for i from 1 to n do
ans := ans*i;
od;
ans;
end:
> fact2 := proc(n::posint)
if (n=1) then
1;
else
n*fact2(n-1);
fi;
end:
Notice how much shorter and clearer the second version is.4.6 However, there is a price to pay: a recursively defined function has a bit more overhead than a non-recursive one. However, the savings in simplicity often overwhelms the minor loss in speed.4.7
To test your understanding, you might try to write a procedure to generate the Fibonacci numbers, which are defined by
With the idea of recursion in our bag of tools, we can now easily write our procedure to generate the Koch curve, using the observation we made in §3, namely that
> Koch:= proc (n::nonnegint)
if (n=0) then
`F`;
else
cat( Koch(n-1), `L`, Koch(n-1), `RR`, Koch(n-1), `L`, Koch(n-1));
fi;
end:
> Koch(2);
If you think about it for a second, you might notice that what we have just
done is to write a little program (Koch
) whose output is a program in
another language (the string of turtle commands which describe
Kn). While this may seem odd at first, doing this sort of thing is
not at all uncommon.
Often, one sees the curve
as one side of a closed plane
figure, the Koch Snowflake (sometimes also called the ``Koch Island''). This
is an infinite length ``curve'' which bounds a finite area, and resembles a
snowflake. It is made by sticking together
three copies of
meeting each other at 60 degrees angles so
that they close up. We do this now:
> KochFlake := proc(n::nonnegint)
ResetTurtle();
SetTurtleAngle(60);
cat(`L`,Koch(n),`RR`,Koch(n),`RR`,Koch(n));
end:
> plots[display](array([[seq(TurtleCmd(KochFlake(i)),i=0..2)],
[seq(TurtleCmd(KochFlake(i)),i=3..5)]]));
What happens to the curve
if we change the height of the
bumps we add at each stage? We can do this easily by changing the angle the
turtle turns when it encounters an R or an L. For example, an angle of
10 degrees gives a curve which is nearly smooth.
> ResetTurtle(); SetTurtleAngle(10);
TurtleCmd(Koch(6));
But an angle of 80 degrees gives a curve which wiggles wildly and almost seems to take up area.
> ResetTurtle(); SetTurtleAngle(80);
TurtleCmd(Koch(6));
We shall make this observation more precise in section 5. You might try some additional experiments on your own, to gain intuition about how the limit curve depends on the parameters. For example, what would happen if you make the angle be 90 degrees? Do you find the result surprising?
Some other variations you might want to try on your own might be to modify the
Koch
procedure so that the bumps are added alternately above and
below the curve, as shown in the following figure:
Here the angle used was less than 60 degrees. What happens for an angle of exactly 60 degrees? How about a larger angle? Can you adjust things so that using 75 degrees angle does not cause self-intersections?
Or, you might try using a different shape of a bump. For example, below we used squares, shrinking the scale first so the bumps don't run into each other. What happens if you vary the scale factor with
SetTurtleScale
?