CPSC 120: Lab Assignment 5

Due at 11:59 pm on Tuesday, 04/05/2016

Home | Calendar | Announcements | Assignments | Example Code | Notes

Reading

Problems

Problem #1

Write a method, connect, which takes as arguments an integer, n and a floating point value, p. The method should plot n points, evenly spaced around a circle. Then, for each pair of points, it should draw a gray line between them with probability p

connect(16,0.05)
connect(16,0.125)
connect(16,0.45)
connect(16,1.0)

Tip #1: This problem involves the drawing of n evenly-spaced points around a circle as a subproblem. That means you can reuse your circleplot solution here (see below).

Tip #2: The key insight for the line drawing is to observe that from each point, we're going to consider every other point (what kind of control structure does this kind of nested iteration?). Then we *might* draw a line to it (with probability p). As a first attempt, try just drawing the lines. Then go back and study the discussion we had in class on probability techniques. In particular, the bubbles.pde sketch from the Example Code on March 11th is very pertinent here.



Problem #2

Make a second version of your connect() method, which connects lines on a spiral instead (again, see below for the basics). Exactly where you connect lines in this case is up to you. Perhaps have one end of each line at the enter of the spiral? Connect lines between points on opposite sides of a spiral (i.e. the angle + PI/2)? It's up to you.



Problem #3

Implement methods for drawing spirographs,by providing methods for drawing hypotrochoids and epicycloids. Before proceeding, take some time to read the tutorial material on this, below. Read it carefully! There isn't much coding to do in this part, and once you can follow the tutorial material, you'll that a lot of it is just translation of formulae into code. Without the background material, however, this part will be extremely difficult or even impossible.

You are to write two methods, hypotrochoid and epitrochoid. Both methods should take at least three floating-point arguments—R, r, and p— corresponding (respectively) to the radius of the ring, of the disc, and of the pen with respect to the disc's center. The methods should draw the corresponding hypotrochoids or epitrochoid.

The basic version of this would simply keep a variable t, denoting the angle of revolution, which is incremented by some small increment, say, 0.01. We can then define a "limit", for the largest t value, and iteratively draw points on the curve until this limit is reached: this limit, of course, is the closest integer to the period of the curve.

int period = ... ;

float t = 0.0;
float incr = 0.01;
int numPlots = (int) (period / incr);

Computing the period of a curve is straightforward, but it requires concepts that we have not learned in this class: recursion and roundoff error in floating point numbers. I suggest instead that you add a 4th parameter to your methods, b, which will be the number of complete revolutions of the disc around the ring (see the discussion of "period", above). This means you'll have to compute the correct argument to b by hand in order to draw a complete curve, but that's okay for this project. Indeed, if you just pick some value out of the air—say, 100 revolutions—and the period is less than that, you'll just be drawing on top of the curve you've already drawn. That makes for a very slightly slower method, but you won't be able to tell the difference.

Exercise your creativity here! Add a parameter to control the color of the curve, or choose a random color each time. Perhaps, too, an option to draw multiple curves, in order to make combined images. Control of pen width? Switching pen color part-way through a drawing? What else?

In addition to the three mandatory parameters and "revolutions" parameter, my version includes a "fast" option parameter (which causes incr to be set at 0.1 rather than 0.01), and a "clear drawing" option which allows the drawing of multiple curves. On execution, each method chooses a random pen color

Here are some sample calls, and the resulting images (note that the last two combine in my version). The "fast drawing" option is set to false in every case:

epitrochoid(0.32,0.1,0.2,5,false,true);
hypotrochoid(0.64,0.2,0.4,5,false,true);
epitrochoid(0.54,0.26,0.26,13,false,true);
hypotrochoid(0.84,0.24,0.4,2,false,false);

   



Tutorial Material

Drawing circles

Below is the code we developed in class for the circelplot() method, which takes two arguments, integers n and r and plots a set of n evenly-spaced dots around a circle with radius r:

circleplot(width/2,height/2,100,8);
circleplot(width/2,height/2,100,16);
circleplot(width/2,height/2,100,128);

     

Here's the circle plotting code that we developed in class on Wednesday (03/30):

void circleplot(int cx, int cy, int r, int n) {
  // Plot a circle around a point (cx,cy), with radius r, using n dots
  
  float ang = 0.0;
  float dAng = (2*PI) / n;

  strokeWeight(1);
  fill(0, 0, 255);
  noStroke();

  int i = 0;
  while (i < n) {
    float x = cx + cos(ang)*r;
    float y = cy + sin(ang)*r;

    ellipse(x, y, 10, 10);

    ang += dAng;
    i++;
  }
}

Drawing spirals

There are other forms of curve you can draw. One we did in class changes the computation of the (x,y) coordinates to multiply each by the current value of the angle (which is increasing). This plots what is known as the Archimedean spiral. Here's a version that does this r revolutions of the spril, drawing n points on each complete revolution, with a scaling factor on the spiral of s (which, in Pearson's presentation is the "increasing radius" value):

void spiralplot(int cx, int cy int n, int s, int r) {
  float ang = 0.0;
  float dAng = (2*PI) / n;

  stroke(0, 0, 255);
  strokeWeight(3);

  while (ang < r*(2*PI)) {
    float x = cx + ang * cos(ang)*s;
    float y = cy + ang * sin(ang)*s;

    ellipse(x, y,5,5);

    ang += dAng;
  }
}

(The scaling factor is necessary to avoid drawing a spiral that is packed together too tightly to see the lines of its curve.)

Try this one out with, for example

spiralplot(width/2,height/2,numc,2,9);

Drawing Spirograph designs

The Spirograph is a classic toy that allows one to make beautiful designs based on curves known as epitrochoids and hypotrochoids. If you've never seen one (and most of you probably haven't, as they have only recently come back into production after decades of unavailability), you can read about them at http://en.wikipedia.org/wiki/Spirograph and at http://mathworld.wolfram.com/Spirograph.html.

To understand these curves, imagine a a larger ring of radius R, fixed against a surface. Now imagine a disc of radius r to which we attach a pen, at a distance p from the center of the disc.

If we put roll the disc around the inside of the ring, the resulting curve is a hypotrochoid (Fig. 1). If we roll it around the outside, we get an epitrochoid (Fig. 2).



Figure 1. The hypotrochoid R = 5, r = 3, p = 5, which has a period of 2π3, or 3 rotations of the disc
(Source: Wikimedia Commons)

hypotrochoids

Let's start by considering the hyptrochoid (the more common of the Spirograph componenents, since it's a lot easier to keep a physical disc stable inside a ring than outside). To draw these, we will calculate the (x,y) coordinates of a point on the curve by computing each coordinate in terms of t, the angle that we have rotated the disc around the ring. Under this view, the (x,y) coordinates of the pen at angle t are given by

So to draw the curve, we just need to pick a few values of t and plot a point at the (x,y) coordinates of each one!

Which values of t? We want to make sure of two things. First, we want to pick values that are evenly spaced across some range. This will give the illusion of an unbroken curve, even though we're not plotting every visible pixel in our drawing. Basically, we figure out how big a t range to draw, break that into a set of n evenly spaced values, and plot each point. My solutions take the size of the t range, divide that by either 0.1 or 0.01 (depending on whether I want a faster drawing or a more precise one), take the closest integer value to that, and use the result as an increment that I repeatedly add to the current t value.

Now for the "t range". Study the animation in Figure 1. You'll notice that it takes 3 rotations of the disc around the ring to complete the curve. In other words, the total angle of rotation is 2π3: this is called the period of the curve. In general, the period of a hypotrochoid can be calculated from the radii of the disc and the ring. Take the fraction r/(R-r) in reduced form: r/(R-r) = b/a. The period is 2πb, so we need b rotations to complete the curve.

epitrochoids

An epitrochoid curve is very similar to a hypotrochoid, except that we roll the disc around the outside of the ring. To draw these curves, we again look at both the x and y coordinates as functions of the angle of rotation. In an epitrochoid, these coordinates are given by

The techniques for drawing epitrochoids are very similar to those for hypotrochoids.

some fun properties

As discussed above, the ratio of r and R-r controls the period of the curve: it is 2πb, where b/a = r/(R-r) in reduced form.

The difference between r and p controls the detail in the curves, in the form of apparent direction changes. If r = p, then both epitrochoids and hypotrochoids will have a number of cusps (sharp corners in the curve): these curves are known as epicycloids and hypocycloids. If r < p, then the curve will have a number of "loops" in its drawing (going outwards for hypotrochoids, in for epitrochoids). Finally, if r > p, then the curve will have no loops at all, but rather a series of "bends" (outwards or inwards), as in the epitrochoid of Figure 2.

The ratio of R and r controls how many of these "changes" occur in the curve (cusps, bends, or loops). If R/r = p/q in reduced form, the curve has p cusps, bends, or loops. This leads to some surprisingly complicated designs with very subtle changes. For example, a curve with R=0.9 & r = 0.3 will have 3 changes over a period of 2π, while a curve with R=0.9 & r = 0.301 will have 900 over a period of 2π301.



Standards

Turn in

As with all assignments for this course, submit the folder containing your Processing sketches. This should be a single folder named "hw5", which will contain your two sketches. You do not need to submit a paper printout of anything. Again, the turnin directory is

~lasseter/classes/cpsc120/username


John H. E. Lasseter