Turtle Graphics

Summary:
We explore MediaScripts's implementation of Turtle
Graphics, a model of graphics based on turtles that draw.

Introduction

As you might expect, there are a wide variety of models for describing
images algorithmically. One of the more interesting models is
typically called turtle graphics, and is based
on a fairly simple and intuitive model of drawing: All drawing is
done by a robotic turtle that has two basic actions: moving forward
and turning. The turtle also has a collection of pens that it use to
draw with. (Alternately, it has a magic pen which can change colors
and tips.)

The turtle graphics model is popular for a number of reasons. One
important reason is that it is simple: At the
core, turtle graphics only requires four operations: moving the turtle
forward, turning the turtle, lifting the pen up, and putting the pen
down. (Often, turtle graphics implementations provide additional
features, but these four suffice.) Given these few operations, plus a few
additional control structures, it is possible to draw a wide variety
of interesting images. Many programmers and designers also appreciate
the challenge of seeing what they can do with these simple operations.

Another reason that turtle graphics is popular is that it is
relatively easy to implement in the physical world. Particularly
with the advent of easy-to-construct robotics kits, such as Lego
Mindstorms™, “anyone”
can build a robot that draws. (In most cases, the unpredictability
of the physical world means that drawings with physical turtles have
an interesting imperfection as compared to those from their digital
counterparts.)

Turtle graphics is also popular because it was a core component of
Logo, one of the most important languages created for novice
programmers. Logo, designed by Seymour Papert at MIT, was intended
as an environment in which children could learn to think about
algorithms and programming. It was surprisingly successful, enough
so that Logo is still used in some contexts, a few decades after it
was first created. Logo and turtle graphics also promote a mode
of teaching and learning called constructionism
in which students learn by playing and experimenting.

MediaScripts's Basic Turtle Graphics Procedures

MediaScript provides a somewhat larger group of turtle graphics
procedures than the basic four. In part, this is because MediaScript
permits you to have more than one turtle. (Multiple turtles can be
useful when you want to draw overlapping figures.)

There are two ways to create a turtle. The most
straightforward is (turtle-newimage-id), which creates a new turtle
associated with a particular image. You will, of course, need to name
that turtle. For instance, if you've already created an image called
canvas, you could create a turtle on that image.

>(define tommy (turtle-new canvas))

One can also clone an existing
turtle with (turtle-cloneturtle). The clone is associated
with the same image and has the same position and orientation as
the original turtle. Once again, when you create a new turtle with
turtle-clone, you should name
that clone.

>(define tommy2 (turtle-clone tommy))

One can, of course, tell turtles to do the four core turtle operations.

(turtle-forward!turtleamt)
advances the turtle the specified amount, drawing if the pen is down.

(turtle-turn!turtledegrees)
turns the turtle clockwise the specified number of degrees.

(turtle-up!turtle)
lifts the turtle's pen.

(turtle-down!turtle)
drops the turtle's pen.

With these procedures, we can draw squares, equilateral triangles, and
even circles.

Orienting the Turtle

In an ideal world, either (a) the programmer knows the position and
direction of the turtle or (b) the programmer can write programs
that are independent of the initial position and direction. In fact,
common turtle coding practice suggests that you should often design
sequences of operations that return a turtle to its original position
and orientation.

However, when experimenting with turtles, a programmer benefits from
the ability to move the turtle to a particular position and orient it
in a particular direction. MediaScript provide two “hacks”
that let you place and orient the turtle precisely.

(turtle-teleport!turtlecolumnrow)
moves the turtle to a particular column and row.

(turtle-face!turtledegrees)
makes the turtle face a direction the specified number of degrees
clockwise from right.

Before we explore more about turtles, let's start by writing a procedure
that places the turtle at (50,50), facing right.

You may notice that this looks a bit different
than other procedures we've written. First, the name
turtle-reset! ends with an exclamation
point. You may recall that we also used exclamation points in many
of the GIMP tools procedures. It is tradition in Scheme that when
procedures change one of their parameters, or the context in which
future procedures are evaluated, we end the names with an
exclamation point.

Second, instead of nesting operations, as we did when creating drawings,
we are sequencing operations. First, we teleport the turtle to
(50,50). Then we turn the turtle to the right.

You'll find both characteristics in the procedures we write that
deal with turtles. That is: We will often change the turtles
(e.g., moving them to new places or making them face other directions)
and we will usually create a sequence of operations for the turtle
to follow.

Turtle Graphics: Initial Explorations

Now that we know the basics of turtles, let's explore the basic operations
visually. First, we'll reset the position of the turtle using the
procedure we just created.

(turtle-reset! tommy)

Not very interesting, is it? It is a tradition that you only see the
ink left by the turtle's pen, and not the turtle itself. However, it's
not very helpful to have invisible turtles if we're trying to understand
the turtle operations. Hence, for this discussion of turtles, we will
use a small figure to show the position and orientation of the turtle.

(turtle-reset! tommy)

So, what happens when we move the turtle forward 25 spaces? Probably
what you'd expect: We get a horizontal line of length 25, and the
turtle is at the end of the line.

(turtle-reset! tommy) (turtle-forward! tommy 25)

Okay, suppose instead of moving the turtle forward, we started by
turning it 135 degrees counter-clockwise or 90 degrees clockwise.
We can envision that something like the following.

(turtle-reset! tommy) (turtle-turn! tommy -135)

(turtle-reset! tommy) (turtle-turn! tommy 90)

Not very exciting yet, is it? But we can start to get some interesting
things when we combine the basic operations into more complex actions and
sequence those actions.

Hmmmm... the same two commands, but in different orders, produced
somewhat different “states” of the turtle and different
images. To some,
the result of action01! are a bit
strange, since the turtle is not pointing the same way as the line.
However, the turtle turns after drawing the line.
Hence, we would expect it to be pointing in a different direction.

You'll note that neither of these actions meets the basic criterion
that, after making a drawing, the programmer is supposed to ensure
that the turtle ends up in its initial position and orientation. That's
okay for now, since we're creating building blocks for making
drawings. However, we should eventually think about how to return the
turtle to its original position (other than by calling
turtle-reset!).

You should also ask yourself whether any of these procedures meet the
criterion that it returns the turtle to the original position and
orientation and, if not, how you might return it to that position and
orientation.

Getting Fancy: Brushes and Colors

It is possible to draw a wide range of fascinating images without every
changing the color or brush shape the turtle uses. However, we can
have even more fun if we are able to change those values. The
following procedures allow us to update the pen. Both procedures take
similar parameters to context-set-fgcolor!
and context-set-brush!, respectively.

(turtle-set-color!turtlecolor)
sets the color of the brush the turtle uses.

(turtle-set-brush!turtlebrush)
sets the brush the turtle uses.

Repeating Commands

As you may have noted in our initial, English-language, discussions
of turtle graphics, turtle-graphics algorithms benefit from the
ability to repeat commands. For example, we might draw a square
by repeating the following action four times.

Turtle Values

In the past, you've seen that brushes are represented by strings and
images are represented by integers. How are turtles represented?
In the current version of MediaScript, turtles are procedures.

>(turtle-new canvas)#<procedure:...heme/gimplib.scm:5480:6>

What does that mean? It means the designers of MediaScript
wanted to make the implementation of turtles a bit obscure.
The main outcome is that you cannot type turtles in directly.
Rather, you must create them with
turtle-new or turtle-clone
and you must name them in order to use them.

The technique of hiding the underlying details of a data type is part
of a strategy called encapsulation. Provided that
the designer of the data type includes sufficiently many procedures
for working with the data (e.g., the various procedures we've provided
for turtles), it should not matter to the client programmer how the
data type is implemented. Among other things, encapsulation allows
the designer to change underlying representation. It turns out that
encapsulation gives benefits to client programmers, too. In particular,
they need not worry about particular details, just about the procedures
provided.

In fact, even when you know the underlying implementation (which you
will for some data types we'll develop over the next few weeks, and
even for turtles toward the end of the course), it is still appropriate
to use the procedures that are designed for manipulating the object,
for both of those reasons. That is, by using those procedures, you
allow yourself or someone else to change the underlying representation,
and, just as importantly, you focus more on how you're using the data
than on how it's represented.

This material is based upon work partially supported by the National
Science Foundation under Grant No. CCLI-0633090. Any opinions, findings,
and conclusions or recommendations expressed in this material are those
of the author(s) and do not necessarily reflect the views of the National
Science Foundation.