Code

Turtle Graphics with Dexy

December 31, 2010   ·   By   ·   Comments Off   ·   Posted in Code

Here’s a fun Python demo for Dexy involving turtle graphics. Python has a built-in turtle graphics library, letting you play with the turtle commands you might remember from Logo (although wihout the lisp).

After LOTS of digging in my stubborn determination to figure out a way to render or save the graphics, I found that Tkinter canvases have the option to render their contents in postscript format, so after writing two new Dexy filters we can automate the entire process as follows:

{
  "turtle-*.py|py|ps2pdf|pdf2png" : {}
}


With this approach, we can render a single Turtle Graphics session to a PNG file (by way of PDF). Let’s look at the Python code first.
First we import all the turtle commands and get our namespace all dirty:

from turtle import *

Then we initialize a screen and set its coordinates to be a little bigger than what we’re going to draw:

s = Screen()
s.setworldcoordinates(-22,-22,22,22)

Set the pen color to something different:

pencolor("#697C82")

And now let’s do some drawing:

for i in range(24):
    circle(10)
    rt(15)

That’s it! Just a tiny bit of drawing code.

Finally, we need to print the postscript to STDOUT.

print s.getcanvas().postscript()

Before we look into the details that make this work, let’s see what we drew:

If you look carefully in the middle you can see the turtle!

The first filter we put this script through is the py filter. This filter takes a Python script and just returns whatever gets written to STDOUT when the script is run. In this case, the only thing we write to STDOUT is the postscript from the canvas, so that’s what is going to get passed to the next filter. This next filter ps2pdf takes postscript and renders it into a PDF. If you wanted PDF output, say for incorporating in a printed document, you could stop here. But for the internet, we want an image format so we use one more filter, pdf2png. You can click on any of those filter aliases to see the source code for those filters.

Let’s done one more example, taken from the demos in the Python source code:

from turtle import Turtle, mainloop, Screen

def tree(plist, l, a, f):
    """ plist is list of pens
    l is length of branch
    a is half of the angle between 2 branches
    f is factor by which branch is shortened
    from level to level."""
    if l > 3:
        lst = []
        for p in plist:
            p.forward(l)
            q = p.clone()
            p.left(a)
            q.right(a)
            lst.append(p)
            lst.append(q)
        for x in tree(lst, l*f, a, f):
            yield None

def maketree():
    p = Turtle()
    p.pencolor("#697C82")
    p.setundobuffer(None)
    p.hideturtle()
    p.speed(0)
    p.tracer(30,0)
    p.left(90)
    p.penup()
    p.forward(-210)
    p.pendown()
    t = tree([p], 200, 65, 0.6375)
    for x in t:
        pass

s = Screen()
maketree()
print s.getcanvas().postscript()

And here’s what this looks like: