## Turtle Graphics

### January 3, 2012

We choose PostScript as our output device, but our use of PostScript will be primitive: a very brief initialization, an even briefer termination, and only `moveto`

`lineto`

commands in between. We will keep track ourselves of the turtle state — the current *x*-position and *y*-position, the current heading, and whether the pen is up or down — because it is hard to get such information back from PostScript to the controlling Scheme script. Here’s the initialization:

`(define (clearscreen)`

(set! xpos 0)

(set! ypos 0)

(set! pen? #t)

(set! head 0)

(send "%!")

(send "initgraphics")

(send "newpath 306 396 moveto")

(send "currentpoint translate")

(send "0 setgray 2 setlinewidth"))

We reset Scheme’s turtle coordinates then `send`

five initialization commands: `%!`

identifies the output as PostScript, `initgraphics`

initializes PostScript to accept graphics commands, `newpath 306 396 moveto`

starts a new drawing and moves the PostScript turtle to the center of an 8%half;-by-11 page, `currentpoint translate`

resets the current PostScript turtle to the point `0,0`

so it is the same as the Scheme turtle, and `0 setgray 2 setlinewidth`

sets a black pen with width 2. There is no `scale`

command, so a turtle step will be PostScript’s default measure of 1/72 of an inch.

The `penup`

and `pendown`

commands are trivial; the global variable `pen?`

is `#t`

when the pen is down:

`(define (penup) (set! pen? #f))`

(define (pendown) (set! pen? #t))

The most complicated commands are `forward`

and `back`

. We compute new coordinates using trigonometry (one degree, which is the measure used by the turtle, is equal to 0.017453292519943295 radians, which is the measure used by the Scheme `sin`

and `cos`

functions), write a PostScript command using either `lineto`

or `moveto`

depending on whether the pen is down or up, and reset the global turtle position:

`(define (forward n)`

(let ((newx (inexact->exact (round

(+ xpos (* n (sin (* head 0.017453292519943295)))))))

(newy (inexact->exact (round

(+ ypos (* n (cos (* head 0.017453292519943295))))))))

(send newx newy (if pen? "lineto" "moveto"))

(set! xpos newx) (set! ypos newy)))

`(define (back n)`

(let ((newx (inexact->exact (round

(- xpos (* n (sin (* head 0.017453292519943295)))))))

(newy (inexact->exact (round

(- ypos (* n (cos (* head 0.017453292519943295))))))))

(send newx newy (if pen? "lineto" "moveto"))

(set! xpos newx) (set! ypos newy)))

`Left`

and `right`

are simpler; they merely reset the global turtle heading, wrapping around at 360 degrees:

`(define (left n) (set! head (modulo (- head n) 360)))`

(define (right n) (set! head (modulo (+ head n) 360)))

`Setpos`

and `setheading`

reset the global turtle state; `setpos`

also moves the PostScript turtle, drawing a line if the pen is down.

`(define (setpos x y)`

(send x y (if pen? "lineto" "moveto"))

(set! xpos x) (set! ypos y))

(define (setheading n) (set! head n))

`Pos`

and `heading`

return the appropriate values from the global turtle state; `done`

performs the very brief termination:

`(define (pos) (values xpos ypos))`

(define (heading) head)

`(define (done) (send "stroke showpage"))`

Finally, we use the `send`

command to write output:

`(define (send x . xs)`

(cond ((null? xs) (display x) (newline))

(else (display x) (display " ") (apply send xs))))

And that’s it. As a demonstration of the library, here is the `tree`

function from Harvey’s book, and the commands to draw the tree shown on the previous page:

`(define (tree size)`

(cond ((< size 5) (forward size) (back size))

(else (forward (/ size 3))

(left 30) (tree (* size 2/3)) (right 30)

(back (/ size 3))

(forward (/ size 2))

(right 25) (tree (/ size 2)) (left 25)

(back (/ size 2))

(forward (* size 5/6))

(right 25) (tree (/ size 2)) (left 25)

(back (* size 5/6)))))

`(with-output-to-file "tree.ps"`

(lambda ()

(clearscreen)

(penup)

(back 300)

(pendown)

(tree 400)

(done)))

You can run the program at http://programmingpraxis.codepad.org/cX7wPlQa.

A module in python 3 and an example tree rewritten. Uses pygame.

[…] you read books about Logo while you were a kid you remember all that fun with turtle graphics, using loops to draw circles and recursion to generate really complicated […]