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 can move forward and turn. 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 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.
MediaScripts's Turtle Graphics Procedures
MediaScript provides a somewhat larger group of turtle graphics procedures.
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
diagrams.)
There are two ways to create a turtle. The most straightforward is
(turtle-new image-id),
which creates a new turtle associated with a particular image. You
will, of course, need to name that turtle.
> (define tommy (turtle-new canvas))
One can also clone an existing
turtle with (turtle-clone
turtle). Once again, 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! turtle amt)
advances the turtle the specified amount.
(turtle-turn! turtle degrees)
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
much more. See if you can figure out what each of these sequences of
instructions do.
; Drawing One
: Drawing Two
; Drawing Three
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! turtle color)
sets the color of the brush the turtle uses.
(turtle-set-brush! turtle brush)
sets the brush the turtle uses.
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. (For the first drawing, the turtle ends up at the
starting position, but facing in a different direction. We can fix
that problem by turning it 90 degrees at the end.)
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! turtle column row)
moves the turtle to a particular column and row.
(turtle-face! turtle degrees)
makes the turtle face a direction the specified number of degrees
clockwise from right.
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 the following commands four times.
(turtle-forward! tommy 40)
(turtle-turn! tommy 90)
Many turtle-based drawing systems, such as the Logo language,
introduce a special notation for turtle repetition. In the
MediaScript library, however, we leave repetition to standard Scheme
control mechanisms. Hence, in your initial explorations of
turtle graphics, you must be a bit more creative in how you repeat
commands. There are at least two options: You can copy and paste
code. For example, if we copy and paste those two lines four
times, we have instructions for drawing a square. We can also put
the drawing instructions on one line in the interactions pane and
repeatedly run those instructions. We'll play a bit with both options in
the corresponding lab.
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), 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.