Turtle

Your browser doesn't do Java.
TurtleKeys.java
Although the objectdraw library has a wide selection of shapes that it allows you to draw, sometimes you want to make a new shape of your own. This can be hard to do if your only option is to somehow combine the existing shapes.

For example, suppose that you want to draw a pentagon. You would have to use a lot of trigonometry to calculate the coordinates of every corner of the pentagon and then connect them with lines. And even then, your pentagon shape would just be lines; you wouldn't be able to fill it in.

There is a better alternative - you could create a Turtle object and tell it what to do to draw you a pentagon. Turtle, like its namesake, can be thought of as something crawling around on the canvas. It follows instructions like "turn left" or "walk forward". And as it goes, it draws a line behind itself. Drawing a pentagon with a Turtle is as simple as telling it five times to move forward and then turn 72 degrees.

Table of Contents

1. Creating a Turtle

When creating a Turtle you have the same options your would usually expect:

public Turtle(double x, double y, DrawingCanvas canvas)
public Turtle(double x, double y, Color color, DrawingCanvas canvas)
public Turtle(Location point, DrawingCanvas canvas)
public Turtle(Location point, Color color, DrawingCanvas canvas)
public Turtle(DrawingCanvas canvas)
public Turtle(Color color, DrawingCanvas canvas)

If you don't specify the location of the Turtle, it will automatically appear in the middle of the canvas. You can always move it (and its sketch) later, using moveSketchTo(), described below.

The Turtle will always start out facing to the left, with its "pen" down so that it will draw as it moves; it will be colored black if you don't give it a color.

2. Giving the Turtle instructions

The most basic commands that you can give to a Turtle involve moving and turning:

public void move()
public void move(double distance)
public void rt()
public void rt(double angle)
public void lt()
public void lt(double angle)

Here, rt() and lt() stand for "right turn" and "left turn". Angles are given in degree measurements. If you use the rt() or lt() methods without parameters, the default is to turn 90°. The default move() distance, if you don't specify a distance, is 40 pixels.

So, for example, if I wanted to draw an equilateral triangle 40 pixels to a side, I could draw it with a Turtle:

Turtle t = new Turtle();
t.move();
t.lt(120);
t.move();
t.lt(120);
t.move();

Notice that in order to make a 60° corner on the triangle, the turtle needs to turn 120° to the left. If I wanted the triangle to be bigger - 100 pixels to a side, say - I would have to specify this distance in the calls to move().
Your browser doesn't do Java.
TurtlePolygon.java

It is also possible, although it is rarely useful, to move a Turtle using any of the standard methods for moving locatable shapes:

public void move(double dx, double dy)
public void moveTo(double x, double y)
public void moveTo(Location point)

The applet to the right will let you click to draw a polygon, moving the Turtle to wherever you clicked and letting it draw a line behind it as it goes.

Sometimes, you want to be able to move the Turtle without it drawing a line as it moves. To do this, you simply tell it to lift its pen up, then move it, then tell it to put its pen back down. Here are the relevant methods:

public void penUp()
public void penDown()
public boolean isPenUp()

Finally, you can get information about the location and heading of a Turtle. The heading is given with 0° being to the left, 90° being up, and so on - the sam way that angles usually are in math.

public double getHeading()
public Location getLocation()
public int getX()
public int getY()
public double getDoubleX()
public double getDoubleY()

You may or may not actually want the little "turtle" picture to appear in your drawing. It helps a bit when you're trying to figure out how to draw something, but in the end you probably want to hide it so that just the sketch will be visible. You can control whether the little turtle picture is shown with these methods:

public void hideTurtle()
public void showTurtle()
public boolean isTurtleHidden()

3. Filling in an area

Your browser doesn't do Java.
MeshTurtleDemo.java
Turtles normally just draw lines, so that what you get from a Turtle is like an ordinary Framed shape. However, you may sometimes want to get a Turtle to fill in the shape that it is drawing. You do this by telling it when you are going to start telling it how to make the filled in shape, and then telling it again when you are done:

public void beginFill(Color fillColor)
public void endFill()

So, if I wanted to fill in with blue the equilateral triangle that I showed you how to draw above, I would do this:

Turtle t = new Turtle();
t.beginFill(Color.BLUE)
t.move();
t.lt(120);
t.move();
t.lt(120);
t.move();
t.endFill()

4. Setting the line color and stroke

You can set both the color and the stroke of a Turtle just as you are accustomed to doing with other objects:

public void setColor(Color color)
public Color getColor()
public void setLineWidth(double width)
public double getLineWidth()
public void setStroke(BasicStroke stroke)
public BasicStroke getStroke()

The important thing to realize about Turtle is that when you change its color or stroke, this does not affect what it has already drawn. Changes to the color or stroke will one change the lines that the turtle draws from that point on. So, if you want a Turtle to draw everything in a particular color or stroke, you need to set that before you start giving it commands.

If you decide later that you want to change the color of part of a Turtle's sketch, there is actually a way to do this:

public void recolorSketch(Color original, Color substitute)

This will make it so that any part of the sketch that was drawn in the color original will now be shown in the color substitute. This "translation" will be applied even to colors drawn after recolorSketch() is called. The original colors are still remembered, so if you want to change colors again, you can call recolorSketch() again.

// Replace all parts originally drawn in black with yellow
t.recolorSketch(Color.BLACK, Color.YELLOW);

// Go back to the original coloring. I could also just pass null as the substitution
t.recolorSketch(Color.BLACK, Color.BLACK);

There is one more method you might occasionally want. If you set the line join of the turtle's stroke to miter or bevel, and then draw some sort of polygon, you might be annoyed that you don't get a nice join right at the end of the polygon, because what you really have there is two ends rather than a joint. You can fix this by calling the method close() once you are done drawing.

5. Moving the Turtle's sketch around

Your browser doesn't do Java.
TurtlePolygons.java
As discussed above, the normal moving methods, like moveTo(), move the turtle, but not its sketch. The turtle jumps to the new location and draws a line behind it. What if you wanted to move the whole shape that the turtle had sketched?

There are a different set of methods for moving the whole sketch around:

public void moveSketch(double dx, double dy)
public void moveSketchTo(Location point)
public void moveSketchTo(double x, double y)

These will all move the sketch such that wherever the Turtle started out when you created it, that point of the sketch is shifted over to the location you told it to move to.

It is also possible to rotate and resize the sketch. It can be rotated and scaled around the same point that the Turtle started at. This means that sometimes you have to be clever in order to get the rotation point where you want it; if you look at the code for my TurtlePolygons demo above, you will see that the Turtle starts out at the center of the polygon and I first move it to the outside before beginning to draw.

public void rotateSketch(double byAngle)
public void setSketchRotation(double angle)
public double getSketchRotation()
public void scaleSketch(double byFactor)
public void setSketchScale(double factor)
public double getSketchScale()

One last thing you might want to do with a Turtle sketch is to make a copy of it. You can do this by creating a new Turtle and passing along to the constructor the Turtle that you want to copy:

public Turtle(Turtle clone, DrawingCanvas canvas)

6. Creating fractals with a Turtle

Your browser doesn't do Java.
TurtleFractal.java
One thing Turtles are very good at is drawing fractals. A fractal is a mathematically defined shape in which every piece of the shape is in some way similar to the shape as a whole. So, for example, the only rule needed to generate the shape shown to the right is that the shape is made up of three smaller copies of itself arranged in a zigzag pattern as shown below it.

Drawing a fractal like this is easy to do using recursion. If I am trying to write a method whose job is to tell a Turtle to draw a fractal of a given length, I can first determine how long the smaller fractals making up that fractal will be. A little geometry should convince you that in this case I need to divide by the square root of three to get from the length of the whole fractal to the length of the pieces. Then, I draw the fractal by telling the turtle to turn left 30°, draw a smaller fractal, turn right 120°, draw a smaller fractal, and so on:

public void fractal(Turtle t, double d) {
   d /= Math.sqrt(3);
   t.lt(30);
   fractal(t, d);
   t.rt(120);
   fractal(t, d);
   t.lt(120);
   fractal(t, d);
   t.rt(30);
}

The only problem here is that there is no base case; the Turtle will keep trying to draw smaller and smaller fractals forever, and never actually move. I can solve that problem by deciding to "cheat" and just draw a line once the distance is small enough not to be noticeable. If you click to zoom in on the fractal above, you'll see that that it is in fact made up of many small lines.

public void fractal(Turtle t, double d) {
   if(d < 2) {
      t.move(d);
   } else {
      d /= Math.sqrt(3);
      t.lt(30);
      fractal(t, d);
      t.rt(120);
      fractal(t, d);
      t.lt(120);
      fractal(t, d);
      t.rt(30);
   }
}

7. Complete listing of the Turtle specification

Here are all the constructors and methods in the Turtle class that aren't among the Shared Shape Methods:

public Turtle(double x, double y, DrawingCanvas canvas)
public Turtle(double x, double y, Color color, DrawingCanvas canvas)
public Turtle(Location point, DrawingCanvas canvas)
public Turtle(Location point, Color color, DrawingCanvas canvas)
public Turtle(DrawingCanvas canvas)
public Turtle(Color color, DrawingCanvas canvas)
public Turtle(Turtle clone, DrawingCanvas canvas)

public void move()
public void move(double distance)
public void rt()
public void rt(double angle)
public void lt()
public void lt(double angle)

public void move(double dx, double dy)
public void moveTo(double x, double y)
public void moveTo(Location point)

public void penUp()
public void penDown()
public boolean isPenUp()

public double getHeading()
public Location getLocation()
public int getX()
public int getY()
public double getDoubleX()
public double getDoubleY()

public void hideTurtle()
public void showTurtle()
public boolean isTurtleHidden()

public void beginFill(Color fillColor)
public void endFill()

public void setColor(Color color)
public Color getColor()
public void setLineWidth(double width)
public double getLineWidth()
public void setStroke(BasicStroke stroke)
public BasicStroke getStroke()

public void recolorSketch(Color original, Color substitute)

public void moveSketch(double dx, double dy)
public void moveSketchTo(Location point)
public void moveSketchTo(double x, double y)

public void rotateSketch(double byAngle)
public void setSketchRotation(double angle)
public double getSketchRotation()
public void scaleSketch(double byFactor)
public void setSketchScale(double factor)
public double getSketchScale()