teaching machines

Fabrication Summer Camp: Day 2

May 15, 2021 by . Filed under public, twoville.

Welcome to the second day of our summer camp! Today we will explore two big ideas: loops and turtle geometry. Like yesterday, we will be drawing, coding, and making.

Caterpillar

Code is like a caterpillar. It is on its way to being something beautiful that will bring people delight. But it’s trapped in a body that doesn’t seem beautiful. Speaking of caterpillars, let’s design one using the ideas we discussed yesterday. Some caterpillars are sort of bulbous, so let’s string together a sequence of overlapping circles:



view
corner = [-10, -10]
size = [128, 20]

circle
center = [0, 0]
color = :black

circle
center = [12, 0]
color = :black

circle
center = [24, 0]
color = :black

circle
center = [36, 0]
color = :black

circle
center = [48, 0]
color = :black

circle
center = [60, 0]
color = :black

circle
center = [72, 0]
color = :black

circle
center = [84, 0]
color = :black

circle
center = [96, 0]
color = :black

circle
center = [108, 0]
color = :black

var twovilleDiv = jQuery('#twoville_caterpillar1');
twovilleDiv.closest('pre').replaceWith(twovilleDiv);
document.getElementById('twoville_form_caterpillar1').submit();

view
corner = [-10, -10]
size = [128, 20]

circle
center = [0, 0]
color = :black

circle
center = [12, 0]
color = :black

circle
center = [24, 0]
color = :black

circle
center = [36, 0]
color = :black

circle
center = [48, 0]
color = :black

circle
center = [60, 0]
color = :black

circle
center = [72, 0]
color = :black

circle
center = [84, 0]
color = :black

circle
center = [96, 0]
color = :black

circle
center = [108, 0]
color = :black



Writing this code wears me out. Even worse, if I later decide to change the radius or the color, I’ll have to change many lines. I’m likely to miss one. The cost of making changes discourages experimentation.

A better solution is to use a loop. Programming languages often support several kinds of loops. We’re going to talk about one: the for loop. A for loop walks through a sequence of numbers. For each value in the sequence, it runs its block of code. The value of the sequence is available in a variable. To walk through the numbers from 0 to 10, we write this loop:



for i to 10
print(i)

var twovilleDiv = jQuery('#twoville_for-to-loop');
twovilleDiv.closest('pre').replaceWith(twovilleDiv);
document.getElementById('twoville_form_for-to-loop').submit();

for i to 10
print(i)



This loop allows us to reduce our circle drawing code to something much shorter and less repetitive:



view
corner = [-10, -10]
size = [128, 20]

for i to 10
circle
center = [i * 12, 0]
color = :black

var twovilleDiv = jQuery('#twoville_caterpillar2');
twovilleDiv.closest('pre').replaceWith(twovilleDiv);
document.getElementById('twoville_form_caterpillar2').submit();

view
corner = [-10, -10]
size = [128, 20]

for i to 10
circle
center = [i * 12, 0]
color = :black



Now it’s much easier to change the color or radius.

If you want to apply a little curvature to the caterpillar and feel comfortable with trigonometric functions, you can alter the y-coordinate of the body segments using the sine function:



view
corner = [-10, -22]
size = [128, 44]

for i to 10
circle
center = [i * 12, sin(i * 40) * 12]
color = :black

var twovilleDiv = jQuery('#twoville_caterpillar3');
twovilleDiv.closest('pre').replaceWith(twovilleDiv);
document.getElementById('twoville_form_caterpillar3').submit();

view
corner = [-10, -22]
size = [128, 44]

for i to 10
circle
center = [i * 12, sin(i * 40) * 12]
color = :black



The for-to loop that we just saw always starts at 0 and stops when it reaches the upper bound. There’s also the for-in loop which allows you start at a different number. It looks like this:



for i in 5..10
print(i)

var twovilleDiv = jQuery('#twoville_for-in-loop');
twovilleDiv.closest('pre').replaceWith(twovilleDiv);
document.getElementById('twoville_form_for-in-loop').submit();

for i in 5..10
print(i)



Notice how 10 is printed. Unlike the for-to, the upper bound is included in the range of numbers that the loop walks through.

Tower

Now it’s your turn to make something. First draw this stack of rectangles on your graph paper:

Label the centers and the sizes of the rectangles.

Then write a Twoville program with a loop that plots them.

Turtle Geometry

So far, we’ve been thinking of space as a grid that we are flying over. We look down and see imaginary streets that intersect. To identify a location, we name its vertical street and its horizontal street.

This isn’t how you think about space when you are physically in the space instead of flying overhead. When you are on a bike or in a car, you think about moving forward and turning. This first-person perspective is sometimes called turtle geometry. Let’s try making a shape with turtle geometry instead of “bird geometry.”

In a moment, you are going to trace out the letter of someone’s name. To prepare you for that task, let’s pretend this shape is a letter:

In fact, this shape is a letter in Russian. It makes a P sound.

We’ll plot this letter with turtle geometry using a polyline, which is like a polygon but is not filled in. It starts off like this, with an additional weight property to control the line thickness:



view
center = [50, 50]
size = [110, 110]

polyline
color = :black
weight = 3

var twovilleDiv = jQuery('#twoville_turtle1');
twovilleDiv.closest('pre').replaceWith(twovilleDiv);
document.getElementById('twoville_form_turtle1').submit();

view
center = [50, 50]
size = [110, 110]

polyline
color = :black
weight = 3



With bird geometry, we used vertex.position to add each corner. With turtle geometry, we start by initially positioning the turtle. It has both a position and a direction or heading. The heading is an angle. A heading of 0 starts the turtle facing to the right. A heading of 90 starts the turtle facing up. Let’s start it facing up and sitting in the bottom-right corner:



view
center = [50, 50]
size = [110, 110]

polyline
color = :black
weight = 3
turtle
position = [100, 0]

var twovilleDiv = jQuery('#twoville_turtle2');
twovilleDiv.closest('pre').replaceWith(twovilleDiv);
document.getElementById('twoville_form_turtle2').submit();

view
center = [50, 50]
size = [110, 110]

polyline
color = :black
weight = 3
turtle
position = [100, 0]



We move the turtle forward with the walk command, which expects a distance property:



view
center = [50, 50]
size = [110, 110]

polyline
color = :black
weight = 3
turtle
position = [100, 0]
walk.distance = 100

var twovilleDiv = jQuery('#twoville_turtle3');
twovilleDiv.closest('pre').replaceWith(twovilleDiv);
document.getElementById('twoville_form_turtle3').submit();

view
center = [50, 50]
size = [110, 110]

polyline
color = :black
weight = 3
turtle
position = [100, 0]
walk.distance = 100



We turn the turtle with the turn command, which expects a degrees property. To turn left at a right angle, we turn 90 degrees:



view
center = [50, 50]
size = [110, 110]

polyline
color = :black
weight = 3
turtle
position = [100, 0]
walk.distance = 100
turn.degrees = 90

var twovilleDiv = jQuery('#twoville_turtle4');
twovilleDiv.closest('pre').replaceWith(twovilleDiv);
document.getElementById('twoville_form_turtle4').submit();

view
center = [50, 50]
size = [110, 110]

polyline
color = :black
weight = 3
turtle
position = [100, 0]
walk.distance = 100
turn.degrees = 90



Fast-forwarding a bit, we arrive at the inner perimeter:



view
center = [50, 50]
size = [110, 110]

polyline
color = :black
weight = 3
turtle
position = [100, 0]
walk.distance = 100
turn.degrees = 90
walk.distance = 100
turn.degrees = 90
walk.distance = 100
turn.degrees = 90
walk.distance = 20

var twovilleDiv = jQuery('#twoville_turtle5');
twovilleDiv.closest('pre').replaceWith(twovilleDiv);
document.getElementById('twoville_form_turtle5').submit();

view
center = [50, 50]
size = [110, 110]

polyline
color = :black
weight = 3
turtle
position = [100, 0]
walk.distance = 100
turn.degrees = 90
walk.distance = 100
turn.degrees = 90
walk.distance = 100
turn.degrees = 90
walk.distance = 20



Our distances change and we must also make turns to the right, which use a negative number of degrees:



view
center = [50, 50]
size = [110, 110]

polyline
color = :black
weight = 3
turtle
position = [100, 0]
walk.distance = 100
turn.degrees = 90
walk.distance = 100
turn.degrees = 90
walk.distance = 100
turn.degrees = 90
walk.distance = 20
turn.degrees = 90
walk.distance = 80
turn.degrees = -90
walk.distance = 60
turn.degrees = -90
walk.distance = 80

var twovilleDiv = jQuery('#twoville_turtle6');
twovilleDiv.closest('pre').replaceWith(twovilleDiv);
document.getElementById('twoville_form_turtle6').submit();

view
center = [50, 50]
size = [110, 110]

polyline
color = :black
weight = 3
turtle
position = [100, 0]
walk.distance = 100
turn.degrees = 90
walk.distance = 100
turn.degrees = 90
walk.distance = 100
turn.degrees = 90
walk.distance = 20
turn.degrees = 90
walk.distance = 80
turn.degrees = -90
walk.distance = 60
turn.degrees = -90
walk.distance = 80



The last leg is not closed. We could walk to close it off, or we could just switch to a polygon:



view
center = [50, 50]
size = [110, 110]

polygon
color = :black
turtle
position = [100, 0]
walk.distance = 100
turn.degrees = 90
walk.distance = 100
turn.degrees = 90
walk.distance = 100
turn.degrees = 90
walk.distance = 20
turn.degrees = 90
walk.distance = 80
turn.degrees = -90
walk.distance = 60
turn.degrees = -90
walk.distance = 80

var twovilleDiv = jQuery('#twoville_turtle7');
twovilleDiv.closest('pre').replaceWith(twovilleDiv);
document.getElementById('twoville_form_turtle7').submit();

view
center = [50, 50]
size = [110, 110]

polygon
color = :black
turtle
position = [100, 0]
walk.distance = 100
turn.degrees = 90
walk.distance = 100
turn.degrees = 90
walk.distance = 100
turn.degrees = 90
walk.distance = 20
turn.degrees = 90
walk.distance = 80
turn.degrees = -90
walk.distance = 60
turn.degrees = -90
walk.distance = 80



Letter

Now it’s time for you to make something of your own. Think of someone you care about. That could be a family member, a friend, or yourself. What is the first letter of that person’s name? If that person’s letter has holes in it, as we see in A, B, D, O, P, Q, and R, think of someone else, or think of a different name to represent that person. Later we’ll see how to add holes to shapes, but not yet.

Once you have a letter, follow these steps:

1. Draw it on your graph paper in a block style. The letters must have thickness; they can’t just be lines.
2. Identity the corner at which you want the turtle to start. Label its position and heading.
3. For each edge, label its length.
4. For each corner, measure how much the turtle turns from its current direction to align with the new edge.
5. Turn your drawing into a Twoville program.

Ask lots of questions. When you’ve finished, we’ll fabricate your letter into a vinyl sticker that you can give to the person you have in mind.

Starfish

We’ve examined loops. We’ve examined turtle geometry. If we put these two ideas together, we can make some interesting and beautiful shapes, like a starfish maybe. As a first step, let’s model a pentagon. From the turtle’s perspective it moves forward, turns some degrees, moves forward, turns some degrees, and so on. It does this five times total. How many degrees does it turn at each bend? In total, it turns a complete circuit of 360 degrees. It has five steps to do it in, so each step is 360 / 5 = 72 degrees.

That leads to this program:



polyline
color = :black
weight = 1
turtle
position = [20, 5]
for i to 5
walk.distance = 60
turn.degrees = 72

var twovilleDiv = jQuery('#twoville_pentagon');
twovilleDiv.closest('pre').replaceWith(twovilleDiv);
document.getElementById('twoville_form_pentagon').submit();

polyline
color = :black
weight = 1
turtle
position = [20, 5]
for i to 5
walk.distance = 60
turn.degrees = 72



How would the program change in order to make a hexagon? We’d have six steps of 60 degrees each. A triangle? Three steps of 120 degrees each. A polygon with $n$ vertices? We’d have $n$ steps of $\frac{360}{n}$ degrees. Consider this parametric version of the same program:



n = 10
polyline
color = :black
weight = 1
turtle
position = [40, 20]
for i to n
walk.distance = 20
turn.degrees = 360.0 / n

var twovilleDiv = jQuery('#twoville_ngon');
twovilleDiv.closest('pre').replaceWith(twovilleDiv);
document.getElementById('twoville_form_ngon').submit();

n = 10
polyline
color = :black
weight = 1
turtle
position = [40, 20]
for i to n
walk.distance = 20
turn.degrees = 360.0 / n



Starfish generally have five arms, but some have 40 or 50. Probably we don’t need to think parametrically right now. Five is good. Here’s my preliminary sketch of the turtle walking along the edge of the starfish:

In my program, I’m going to start the turtle off at the bottom-right of the top arm, pointing upward:



view
center = [-2.5, 0]
size = [50, 50]

polyline
color = :black
weight = 0.2
turtle
position = [0, 0]

var twovilleDiv = jQuery('#twoville_starfish1');
twovilleDiv.closest('pre').replaceWith(twovilleDiv);
document.getElementById('twoville_form_starfish1').submit();

view
center = [-2.5, 0]
size = [50, 50]

polyline
color = :black
weight = 0.2
turtle
position = [0, 0]



Then I trace out the arm, which is currently very boxy:



view
center = [-2.5, 0]
size = [50, 50]

polyline
color = :black
weight = 0.2
turtle
position = [0, 0]
walk.distance = 20
turn.degrees = 90
walk.distance = 5
turn.degrees = 90
walk.distance = 20

var twovilleDiv = jQuery('#twoville_starfish2');
twovilleDiv.closest('pre').replaceWith(twovilleDiv);
document.getElementById('twoville_form_starfish2').submit();

view
center = [-2.5, 0]
size = [50, 50]

polyline
color = :black
weight = 0.2
turtle
position = [0, 0]
walk.distance = 20
turn.degrees = 90
walk.distance = 5
turn.degrees = 90
walk.distance = 20



To get five of these arms, I put this code in a for-to loop. But first I need to turn at the armpit. This is a right turn, so the number of degrees will be negative. The angle is bigger than a right angle, so the number will be greater than 90. Through either experimentation or math, we’ll find that number that we need is -108. Here’s our completed, repeated path:



view
center = [-2.5, 0]
size = [50, 50]

polyline
color = :black
weight = 0.2
turtle
position = [0, 0]
for i to 5
walk.distance = 20
turn.degrees = 90
walk.distance = 5
turn.degrees = 90
walk.distance = 20
turn.degrees = -108

var twovilleDiv = jQuery('#twoville_starfish3');
twovilleDiv.closest('pre').replaceWith(twovilleDiv);
document.getElementById('twoville_form_starfish3').submit();

view
center = [-2.5, 0]
size = [50, 50]

polyline
color = :black
weight = 0.2
turtle
position = [0, 0]
for i to 5
walk.distance = 20
turn.degrees = 90
walk.distance = 5
turn.degrees = 90
walk.distance = 20
turn.degrees = -108



The final step is to fill the starfish in. We could switch polyline to polygon, but the arms would be blocky. If we switch to an ungon, then we’ll get rounded corners on the arms:



view
center = [-2.5, 0]
size = [50, 50]

ungon
color = :black
turtle
position = [0, 0]
for i to 5
walk.distance = 20
turn.degrees = 90
walk.distance = 5
turn.degrees = 90
walk.distance = 20
turn.degrees = -108

var twovilleDiv = jQuery('#twoville_starfish4');
twovilleDiv.closest('pre').replaceWith(twovilleDiv);
document.getElementById('twoville_form_starfish4').submit();

view
center = [-2.5, 0]
size = [50, 50]

ungon
color = :black
turtle
position = [0, 0]
for i to 5
walk.distance = 20
turn.degrees = 90
walk.distance = 5
turn.degrees = 90
walk.distance = 20
turn.degrees = -108



Shape Jam

Just like yesterday, we are going to have a shape jam. Your “theme” for today is to use turtle geometry and loops. Follow these steps in making your shape:

1. Start by drawing on graph paper.
2. Get your design inspected by a teacher to make sure it’s something we can fabricate.
3. Mark the turtle’s starting position and heading, the distances of each walk, and the degrees of each turn.
4. Code up your shape in Twoville.

You will have about 30 minutes to make your design. Use that time to make something interesting that exercises your creativity and your brain. We’ll turn your creation into a vinyl sticker.