Turtle Graphics:  Classical Shapes

Comp 110 Course Module 11a

LOGO is a simple language for teaching programming to young children by using Turtle Graphics.  But Turtle Graphics is much more than just a toy for young children.   In their book Turtle Geometry (MIT Press), Abelson and DiSessa use Turtle Graphics to investigate many challenging topics, ranging from elementary differential geometry and topology to Einstein's General Theory of Relativity.  The study of geometry using programming is the branch of Computer Science called Computational Geometry.  In this module, we will develop the LOGO language inside of Mathematica and then use LOGO to build a variety of interesting shapes.

Turtle Global Variables

In Turtle Graphics, the computer keeps track of two global parameters:  
	i.   position = the current location (xy-coordinates) of the turtle
	ii.  direction = the current heading (uv-coordinates) of the turtle -- which way the turtle is facing.
Position is a point;  direction is a vector.  Points are represented by dots on the screen;  vectors by arrows emanating from points.  Points have position, but no direction or length;  vectors have direction and length, but no fixed position.  (Recall Newton's Universal Law of Gravity.  The planets are represented by points;  the force of gravity is represented by vectors.)  Turtles are much like the billiard balls from Module 9.  The positions of the billiard balls are points;  their velocities are vectors.  The difference between billiard balls and turtles is that billiard balls move according to the laws of classical mechanics, whereas we shall write our own programs to control the motion of the turtle.

A schematic diagram of a turtle, represented by a point (location) and a vector (heading).

In order to display the path of the turtle in Mathematica, we shall also keep a list called turtlepath of all the line segments that the turtle traverses on her journey.

Initialization

We begin with a program init that initializes the turtle position to the origin, the turtle direction to the unit vector pointing in the x-direction, and the turtlepath to the empty list.

init:=Module[{},position ={0,0};direction={1,0}; turtlepath={}]

Turtle Commands:  Forward, Turn, and Resize

In classical LOGO there are only two commands:  forward and turn.  
	Forward changes the location of the turtle, but leaves her direction unchanged.
	Turn changes the direction of the turtle, but leaves her position unchanged.

The forward command is a function of a single variable, distance.  The forward command moves the turtle to the new location:
	new location = current location + distance × current direction vector
Forward also updates the turtlepath by adding a new line segment from the current turtle position to the new turtle position to list of lines in turtlepath.

The turn command is a function of a single variable, angle.  The turn command does not move the turtle, but turn changes the turtle's heading by rotating the turtle direction vector by the given angle (angles in this module are measured in degrees).  To compute the new direction, recall that in polar coordinates if r is the length of the direction vector (u,v) and θ is the angle the direction vector (u,v) makes with the x-axis, then:
	(Subscript[u, current]) = r cos(θ)
	(Subscript[v, current]) = r sin(θ)
If we rotate the direction vector by an angle α, then
	(Subscript[u, new]) = r cos(θ+α)
	(Subscript[v, new]) = r sin(θ+α)
Applying the trigonometric identities
	cos(θ+α) = cos(θ) cos(α) - sin(θ) sin(α)
	sin(θ+α) = sin(θ) cos(α) + cos(θ) sin(α)
yields
	(Subscript[u, new]) = r cos(θ+α) = r cos(θ) cos(α) - r sin(θ) sin(α) 
	(Subscript[v, new]) = r sin(θ+α) = r sin(θ) cos(α) + r cos(θ) sin(α) 
But
	(Subscript[u, current]) = r cos(θ)
	(Subscript[v, current]) = r sin(θ)
so 
	(Subscript[u, new]) = (Subscript[u, current]) cos(α) - (Subscript[v, current])sin(α)
	(Subscript[v, new])  = vcurrent cos(α) + (Subscript[u, current])sin(α)
Typically we shall represent these equations in matrix form:
	((Subscript[u, new])  (Subscript[v, new])) = ((Subscript[u, current])  vcurrent) (({{cos(α), sin(α)}, {-sin(α), cos(α)}})).

Vectors have both direction and length.  The turn command changes the turtle's heading by rotating the turtle's direction vector, but we can also change the turtle's step size by changing the length of the turtle's direction vector.  The resize command is a function of a single variable, the scalefactor.  The resize command rescales the turtle step size by setting:
	new direction vector = scalefactor × current direction vector
or equivalently
	(Subscript[u, new]) = scalefactor  (Subscript[u, current]) 
	(Subscript[v, new])  = scalefactor  vcurrent 
Again we can write this transformation in matrix notation:
	((Subscript[u, new])  (Subscript[v, new])) = ((Subscript[u, current])  vcurrent) (({{scalefactor, 0}, {0, scalefactor}})).

Implementation

In our version of LOGO there are four turtle commands:  forward, move, turn, and resize.  THESE ARE THE ONLY PERMISSIBLE TURTLE COMMANDS.  A command to move the turtle to a specific (x,y) location is not allowed, except in the init command.
The forward command takes as input a single parameter, distance.  The result of the forward command is to move the turtle to her new location and to update the list in turtlepath by inserting a new line segment into turtlepath.
The move command is the same as the forward command, except that the move command does not update the list in turtlepath.
The turn command takes as input a single parameter, angle, measured in degrees (see Degree in the Documentation Center).  The result of the turn command is to change the turtle's heading by rotating the turtle direction vector by the given angle.
The resize command takes as input a single parameter, scalefactor.  The result of the resize command is to change the turtle's step size by scaling the turtle's direction vector by the given scalefactor.

Exercises

1.  Below I have implemented the forward and turn commands.  Your job is to implement the move and resize commands.

forward[dist_]:=Module[{oldposition=position},position=oldposition + dist(direction);AppendTo[turtlepath,Line[{oldposition,position}]]];


turn[angle_]:=direction=N[ direction .(({{Cos[angle Degree], Sin[angle Degree]}, {-Sin[angle Degree], Cos[angle Degree]}}))]

2.  Later we shall want to display the path of the turtle.  Write a program displayturtlepath[r,g,b,t] to display the path of the turtle by displaying the list of line segments in the list turtlepath.  The parameters r,g,b should control the color of the path and the parameter t should control the thickness of the path.

Polygons

Using the forward and turn commands, you can now make simple shapes by ordering the turtle around.  For example, the following program will move the turtle along a square path:

square[size_]:=Do[forward[size];turn[90],{4}]

You can test the square procedure with your displayturtlepath program to make sure that square really does generate a square.  Notice that we start with the init routine to initialize the position and location of the turtle and to clear out any previous turtle paths.

Module[{},init;square[1];displayturtlepath[0,0,0,.0035]]

Exercises

Below are turtle programs triangle, poly, and circle that generate a triangle, a polygon with an arbitrary number of sides, and a circle.

The poly program takes as input two parameters:  the size of the sides of a regular polygon, and an integer, n, equal to the number of vertices of the polygon.  The poly program produces as output a list in turtlepath consisting of the edges of a regular polygon with n sides.  (Note that turtle angles are exterior angles, so the angles in the turn commands in the poly program always sum to 360 degrees.)  The circle program creates the circle as a regular polygon with lots of sides.

1.  Your job is to complete the following programs, and then to draw figures of triangles, polygons, and circles.

2.  After you complete the poly program, use Manipulate to generate a slider to control the number of sides in the program to display the polygon.

triangle[size_]:=Do[forward[howmuch];turn[howmuch],{howmany}]

poly[size_,numsides_]:=Do[forward[howmuch];turn[howmuch],{howmany}]

circle[size_]:=Do[forward[howmuch];turn[howmuch],{howmany}]

Stars

There are several different ways to generate stars in LOGO.  We shall investigate three different methods below.

POLYSTAR

The easiest way to generate stars in LOGO is to simply iterate the forward and turn commands for fixed distances and angles.  Consider the following polystar program.

polystar[size_, angle_, n_]:=Do[forward[size];turn[angle],{n}]

Investigate the turtlepath generated by polystar for different values of angle and n, and answer the following questions:

1.  For which values of angle and n does polystar generate a regular polygon?

2.  For which values of angle and n does polystar generate the following star?

3.  For which values of angle and n does polystar generate an n-pointed star?
4.  What is the turtle path generated by polystar for irrational values of angle?

(Hint:  Use Manipulate to generate a slider to try out lots of different values for angle.)

TRISTAR

Here are somewhat different looking stars from those generated by polystar.

1.  Write a turtle program tristar to generate stars of this type with an arbitrary number of points.  (Hint:  Consider the angles at the points of the star and at the vertices between the points of the star.  What is the sum of these two angles?)

2.  Use Manipulate to generate a slider to control the number of points of the stars in the program used to display these stars.

Star of David

Here is yet another type of star:  the Star of David.

1.  Write a turtle program stardavid to draw the Star of David.  (Hint:  Make two triangles.)

Spirals

By iterating the forward and turn commands, you can create polygons and stars (see the polystar program).  By iterating the forward, turn, and resize commands, you can create spirals like the ones pictured below.

1.  Write a turtle program spiral[size, angle, scalefactor] to generate spiral turtlepaths.

2.  Investigate the turtlepaths generated by spiral for different values of angle and scalefactor.

3.  Use Manipulate to generate a slider to control the angles between the spiral arms generated by the spiral program.  For which values of angle does the spiral program generate the following spirals?

Rosettes

A rosette is a regular polygon together with all its diagonals.  Below are two rosettes:  one for a polygon with 5 sides, and one for a polygon with 19 sides

To create rosettes using only the forward and turn commands, you need to precompute the angles between adjacent diagonals as well as the length of each diagonal.
Angles are easy.  For a regular polygon with n sides,
	angle between diagonals = (π/n) = α.
This formula is a consequence of the fact that a regular polygon is inscribed in a circle and equal chords subtend equal arcs.  (Warning:  Here α is measured in radians, but the turn command expects degrees, not radians.)
The lengths of the diagonals are a bit harder, but they can be computed by using the Law of Cosines twice, first to compute the circumradius of a regular polygon with side s, and then applying this result for the circumradius to compute the length of the kth diagonal.  This analysis leads to the formula
	length of kth diagonal = ((Sin(k α))/(Sin(α)))s        k=1,...,n-1.
Notice that the first and last diagonals are actually the sides of the polygon, so if you draw the polygon you need not redraw these sides.

1.  Write a turtle program rosette[s, n] to generate rosettes for regular polygons with n sides each side of length s. 
(Hint:  One way to proceed is to draw all the diagonal emanating from one vertex and then move to the next vertex.)

2.  Use Manipulate to generate a slider to control the number of sides n in the program used to display the rosettes built by rosette[s, n].

Shift, Spin, and Scale

You can shift, spin, and scale turtle programs to make more interesting patterns from simple turtlepaths.

Shift (Translation)

The shift program takes four inputs:  
i.    a turtle program;
ii.   a list of parameters to the turtle program;
iii.  the number of times n that you want to perform the shift;
iv.  the distance you want to shift the curve generated by the original turtle program.
By passing the name of a turtle program to shift, you can generate many shifted copies of the same turtle path.  Below are examples of the shift program applied to the square and circle programs.

shift[turtleprogram_,parameterList_,n_,dist_]:=Do[Apply[turtleprogram,parameterList];move[dist],{n}]

Module[{},init;shift[square,{1},5,2];displayturtlepath[0,0,0,.0025]]

Module[{},init;shift[circle,{7},8,10];displayturtlepath[0,0,0,.0025]]

Spin (Rotation)

The spin program takes four inputs:  
i.    a turtle program;
ii.   a list of parameters to the turtle program;
iii.  the number of times n that you want to perform the spin;
iv.  the angle through which you want to spin the curve generated by the original turtle program.
By passing the name of a turtle program to spin, you can generate many rotated copies of the same turtle path.  Below are examples of the spin program applied to the triangle and circle programs.

Exercises

1.  Write a turtle program spin[turtleprogram, parameterlist, n, angle] to spin arbitrary turtle programs n times through the given angle.

2.  Investigate the turtlepaths generated by applying the spin procedure to different turtle programs, such as polystar, rosette, and spiral.

The spin program applied to the rosette.

Scale (Uniform Scaling)

The scale program takes four inputs:  
i.    a turtle program;
ii.   a list of parameters to the turtle program;
iii.  a scalefactor;
iv.  the number of times n that you want to reproduce the curve generated by the original turtle program rescaled by the scalefactor.
By passing the name of a turtle program to scale, you can generate many scaled copies of the same turtle path.  Below are examples of the scale program applied to the poly and polystar programs to generate some interesting new turtle patterns.

Exercises

1.  Write a turtle program scale[turtleprogram, parameterlist, n, scalefactor] to scale arbitrary turtle programs n times by the given scalefactor.

2.  Investigate the turtlepaths generated by applying the scale procedure to different turtle programs, such as polystar, rosette, and spiral.

3.  Apply the shift and spin programs to the scale program to generate some interesting new turtle patterns such as the ones shown below.

Extra Credit

If you have some spare time, you may work on the following extra credit problems.

Polygons Inscribed in a Circle

Below are two examples of polygons inscribed in a circle.

Exercises

1.  Write a turtle program polyincircle[size, n] to generate an n-sided regular polygon whose sides have length size inscribed in a circle.
(Hint:   You will need to use the Law of Cosines to relate the length of a side of the polygon to the radius of the circumscribing circle.  Then you will need to relate the radius the circle to its circumference, which is given by the number of steps the turtle takes as she traverses the circle multiplied by her step size.)

2.  After you complete the polyincircle program, use Manipulate to generate a slider to control the number of sides in the program to display the polygon inscribed in the circle.

Ellipses

A circle is just a polygon with many, many sides.  The ellipse is just a circle, where the turtle varies her step size as she travels around the circumference.  Notice the four-fold symmetry of the ellipse.

Exercises

1.  Write a turtle program ellipse[size, scalefactor] to generate the ellipse. 
(Hint:   To generate a program for making an ellipse, first write a helper program to generate one quarter of the ellipse, then tackle the entire ellipse.)

2.  Apply the spin procedure to the ellipse program to generate turtlepaths like those illustrated below.