6 of 7 in Python Fractals

All we have to do to complete our LSystem class is implement the actual actions for each character. We'll use python's turtle module, because L-Systems yield themselves very well to turtle drawing. We'll make a turtle, which is basically just a pen with some methods like forward, left, and right and we'll pass it to the initializer of LSystem. Then when we are implementing the action functions, we'll just pass the real work off to the turtle:

 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
class LSystem(GeneratorList):
    def __init__(self, turtle, start, rules, angle, heading=0):
        self.turtle = turtle
    ...
    def forward(self):
        self.turtle.forward(self.size)

    def right(self):
        self.turtle.right(self.angle)

    def left(self):
        self.turtle.left(self.angle)

    def go(self):
        self.turtle.up()
        self.turtle.forward(self.size)
        self.turtle.down()

    def save(self):
        x, y, h = self.turtle.xcor(), self.turtle.ycor(), self.turtle.heading()
        self.states.append((x, y, h))

    def restore(self):
        turtle.up()
        x, y, h = self.states.pop()
        turtle.setx(x)
        turtle.sety(y)
        turtle.setheading(h)
        turtle.down()

It doesn't get much easier than this.

We do need to edit the draw method a little bit, though. We need to initialize heading and, as you may have noticed, we're going to want to set a size value for forward and go. We could hard-code it, but we're going to want to be able to draw these things in different sizes. Here's the changes to the draw function:

1
2
3
4
    def draw(self, index, size=1):
        self.turtle.setheading(self.heading)
        self.size = size
        ...

Alright! Let's fire this baby up and see what she can do! Fire up a python REPL and try the following:

Remember to replace fractals in import fractals below with the name of your python file. You can grab a copy here if you'd like.

1
2
3
4
5
6
>>> from turtle import Turtle
>>> from fractals import LSystem
>>> turtle = Turtle()
>>> turtle.speed('fastest')
>>> dragon = LSystem(turtle, 'FX', {'X': 'X+YF', 'Y': 'FX-Y'}, 90)
>>> dragon.draw(11) # 11 is fairly cool, but small enough to not take long.

Awesome! Check it out:

The dragon you just drew

We just made a fractal! Here's some other things our simple little generator can do:

Sierpinsky 7 Plant 6 Snowflake 4 Dragon 13

And here's the LSystems that made them:

1
2
3
4
sierpinsky = LSystem(turtle, 'FA', {'FA': 'FB-FA-FB', 'FB': 'FA+FB+FA'}, 60)
plant = LSystem(turtle, 'FX', {'X': 'F-[[X]+X]+F[+FX]-X', 'F': 'FF'}, 25)
snowflake = LSystem(turtle, 'F++F++F', {'F': 'F-F++F-F'}, 60)
dragon = LSystem(turtle, 'FX', {'X': 'X+YF', 'Y': 'FX-Y'}, 90)

Not bad for just a generator and a class.

That's all I have for tonight. If you drop by tomorrow, I'll show you how to add some nice colors.

Published on April 24, 2009. Last updated on May 17, 2009.
3 comments so far. Add your own
Fahri Basegmez
April 25, 2009

Very nice example (and presentation) do demonstrate Python's expressiveness. Just a nitpick "serpinski" should be "sierpinski". Your new header image looks great now.

Fahri

Schwartzy
April 26, 2009

Hey nice job Nate. I tested it out and it works really well. It's pretty sweet. Is there anyway to make it larger though? Maybe more pixels per call?

software developers
December 04, 2009

Cool,

Keep up the good work,

Thanks