WORKSHOP/SEMINAR
PARAMETRIC RAPID PROTOTYPING: Chapter 3
For
Internal UVa. Use Only: Draft: February 2, 2008 Copyright © 2008 by Earl Mark, University of Virginia, all rights reserved. Disclaimer |
Relations Among Parts of a Graphic Figure
The previous chapter examined the nature of simple graphics programs and relatively straightforward data types. The oculus is the most advanced of the graphic figures we analyzed, relying upon the use of several more primitive elements (e.g., lines, arcs, circle) within the procedure used to draw it. Within this chapter, we examine graphics programs that have a more advanced structure. That is, we will now begin to examine how the order of some graphic compositions might be characterized not just as a series of drawing steps, but also in terms of certain recurring relationships between its parts.
A distinction can be made between a figure that is hierarchical and one in which a different kind of ordering principle may also be found. As an example of the former case, the Euclidean geometry included by Serlio in his "flowers", such as point, line, circle, etc. are each laid out with hierarchically dependent definitions. The most primitive of these definitions is of a point as "an indivisible thing, which has in itself no dimension" We then have the basis to describe a "line as a straight and continuous representation from one point to another, having length without width". That is, the definition of a line depends upon the notion of points.
line; composed of points
We can also see a of hierarchy of descriptions further developed in the definition of "Parallels" which are dependent upon the notion of "two lines which continue at an equal distance". That is, this hierarchy consists parallels which are described in terms of lines, and in turn, lines which are described in terms of points. We add a further level to this hierarchy in the definition that a "plane is made up of two equidistant lines closed off at the sides, that is a thing which has length and breadth without depth." In other words, the top of the hierarchy is the plane, which is in turn described in terms of parallel lines, and, in turn, parallel lines are described in terms of lines, and finallylines are described in terms of points.
plane; composed of parallel lines; composed of lines; composed of points.
Other kinds of graphic figures may also be broken down into parts. However, the relationship between the whole figure and its parts might be described in non-hierarchical terms. A graphic figure might consist of several equivalent parts each bearing a specified relationship to each other. We might express the relationship a number of ways. One special case is that of a recurring relation that is repeated within the graphic figure of doubling circles and squares.
Recurring Relations
We will now begin to examine in detail how the order of a specific composition might be characterized as a recurring set of relations between graphic elements. We want to describe a geometry composed of a series of circles and squares below as being driven by the relationship of one graphic element to another another in a series of repeated steps.
Doubling of the Circle and Square Animation
From Serlio's Book on Geometry, we have a description of how to derive this proportional series of relationships between a circle and a square, and also, incidentally, a proof that one is the double of the other:
"The doubling of a circle should be done in this way. Given the small circle in a perfect square delimited by four lines A, B, E, and F, and having drawn a circle outside it which touches the four corners, the large circle will be double the smaller one. | ![]() |
The proof of this: if the smaller circle fitted inside a square A, B, E, F, and | ![]() |
the large circle
fitted inside a square C, B, E, F, which is double the smaller one - as
I showed above * - it follows that the large circle is double the smaller one,
as can be understood from the two circles K, L. " * to see this relationship, draw lines from the center of the larger square to the mid-point of each of its sides. The larger square is thus divided into four quadrants. Now rotate the inner square 45 degrees. The edges of the inner square bisect the quadrants of the outer square. Thus, the inner square has half the area of the outer square. |
![]() |
Serlio notes practical applications of this technique in that the "The proiettura, that is the protrusion of the the Tuscan base described by Vetruvius is derived from this. It is also described where he discusses foundations which should be doubled owing to the works which go on top, because of the projections which have to rest upon the masonry." [from translation by Hart and Hicks].
A variation on this technique was the so-called secret of the medieval masons. The secret described how medieval masons would determine with string the inner proportions of a pedestal from its outer base. This basic proportion is also repeated in many other constructions, such as the proportions of a cloister walkway to the garden at the rear of a Gothic Cathedral, or in the delicate patterns of tracery in stained glass windows. The so-called secret was based on the following procedure which results in an inverse doubling of the circle and square. That is, we start with the larger figures first, and use them to develop the the inscribed figures:
Take a given length of string and mark off one side of a square. | ![]() |
Using the same length of string, mark off the additional three sides of the square. | ![]() |
Take two additional strings as diagonals and insure that they intersect each other at their respective midpoints. (You could imagine that a mason might fold a string in half to find its mid-point.). | ![]() |
Place a string ffrom the intersection of the diagonals to the mid-point of one the sides of the square. | ![]() |
Rotate the length of this new string four times, marking off a point on each of the four diagonals. | ![]() |
These four points will determine the inner-most square. | ![]() |
Lets now take a look at the following animation of the so-called secret method. In this case the construction is used to develop the proportions of a pedestal to its base.
The Secret of the Medieval Masons Animation
Describing A Recurring Relation As An Procedure
There are a number of ways to describe the graphic figure of the doubling circles as a procedure. One method is a brute force approach. That is, we can describe the steps of this procedure as though they were each unique and bear no similarity to one another. A summary of this procedure might be:
Step 1: Draw A Circle
At The Point 0.0 ,0.0 ,0.0 with Radius 4.0. Step 2: Draw the next outer Square that circumscribes the Circle. Step 3: Draw the next outer Circle that circumscribes the last Square Step 4: Draw the next outer Square that circumscribes the last Circle. |
The GC script for such a procedure has the exact same organization. We can see this at a rough glance by noticing that the main steps 1 though 4 have been embedded in the script as shown in the text box below. The actually creating of the circles and squares in each part of the script is handled by invoking circle and square drawing procedures:
The statement "circle1.ByCenterRadius(centerPoint, radius, baseCS.XYPlane);" handles
drawing the first circle of step 1.
The statement "square1.ByVertices({pointNE, pointNW, pointSW, pointSE});" is used to draw the next outer square in step 2.
The statement "circle2.ByCenterRadius(centerPoint, radius, baseCS.XYPlane);" is used to draw the next circle in step 3.
Finally, the statement "square2.ByVertices({pointNE, pointNW, pointSW, pointSE})" is used to draw
the next square in step 4.
function(){ //Draws the doubling of the circle, from Serlio, plate 3r, Book On Geometry //define center coordinates of circle Point centerPoint = new Point(); double xval, yval, zval, radius; //Step 1: Draw A Circle At The Point 0.0 ,0.0 ,0.0 with Radius 4.0. radius = 4; xval = 0; yval = 0; zval = 0; centerPoint.ByCartesianCoordinates(baseCS, xval, yval, zval); //draw circle using center and radius Circle circle1 = new Circle(this); circle1.ByCenterRadius(centerPoint, radius, baseCS.XYPlane); //Step 2: Draw the next outer Square that circumscribes the Circle. //initialize and save memory for points Point pointNE = new Point(); Point pointNW = new Point(); Point pointSW = new Point(); Point pointSE = new Point(); //locate the coordinates of the NE point xval = radius; yval = radius; zval = 0; //use coordinates to determine the NE point pointNE.ByCartesianCoordinates(baseCS, xval, yval, zval); //locate the coordinates of the NW point xval = -1 * radius; yval = radius; zval = 0; //use coords to determine the NW point pointNW.ByCartesianCoordinates(baseCS, xval, yval, zval); //locate the coordinates of the SW point xval = -1 * radius; yval = -1 * radius; zval = 0; //use coords to determine the SW point pointSW.ByCartesianCoordinates(baseCS, xval, yval, zval); //locate the coordinates of the SE point xval = radius; yval = -1 * radius; zval = 0; //use coords to determine the SE point pointSE.ByCartesianCoordinates(baseCS, xval, yval, zval); Polygon square1 = new Polygon(this); square1.ByVertices({pointNE, pointNW, pointSW, pointSE}); //Step 3: Draw the next outer Circle that circumscribes the last Square //determine radius for second circle radius = Sqrt(Pow (radius, 2)+ Pow(radius, 2)); //draw circle using center and radius Circle circle2 = new Circle(this); circle2.ByCenterRadius(centerPoint, radius, baseCS.XYPlane); //Step 4: Draw the next outer Square that circumscribes the last Circle. //locate the coordinates of the NE point xval = radius; yval = radius; zval = 0; //use coordinates to determine the NE point pointNE.ByCartesianCoordinates(baseCS, xval, yval, zval); //locate the coordinates of the NW point xval = -1 * radius; yval = radius; zval = 0; //use coords to determine the NW point pointNW.ByCartesianCoordinates(baseCS, xval, yval, zval); //locate the coordinates of the SW point xval = -1 * radius; yval = -1 * radius; zval = 0; //use coords to determine the SW point pointSW.ByCartesianCoordinates(baseCS, xval, yval, zval); //locate the coordinates of the SE point xval = radius; yval = -1 * radius; zval = 0; //use coords to determine the SE point pointSE.ByCartesianCoordinates(baseCS, xval, yval, zval);//<<<<< //draw second square Polygon square2 = new Polygon(this); square2.ByVertices({pointNE, pointNW, pointSW, pointSE}); } |
Looking at this GC script in detail, note that we u Pythagorean theorem to calculate the size of the successive square in step 4. In particular, we can see how this works if we use Serlio's figures for the doubling circle described in figure 1. First look at the distance from the center of small circle K to the corner point a of the smaller square. This distance is equivalent to the corresponding distance from the center of large circle L to any point on its circumference, or in other words the radius of circle L. Now lets assume that we are given the radius of small circle K (radiusK), and we need to determine the radius of large circle L (radiusL). Calculating radiusL will be the key to the success of the procedure.
Recognizing The Recurring Pattern
By inspecting the graphic figure for small circle K, lets assume that a line representing its radius is rotated to12 noon.. Furthermore, assume that it forms one of two legs of a right triangle. Lets also assume that the hypotenuse of this right triangle goes from the center of large circle L to the corner point c. It should now become obvious that the second leg of this triangle is equivalent to the radius of small circle K pointed in the direction of 9 p.m.. We therefore have arrived at a right triangle, where the radius distance of large circle L is equal to the distance of the hypotenuse, and the radius distance of small circle K is equivalent to the the distance of each its legs.. By Pythagorean's theorem we then have that the radius of the large circle L is equal to:
radiusL = Sqrt(Pow (radiusK, 2)+ Pow(radiusK, 2));
where Sqrt is a square root function, and Pow is the exponentiation function.
More conveniently, we can use use the variable radius twice in the same expression to assign it a new value (left-hand side of expression below) based upon its former value:
radius = Sqrt(Pow (radius, 2)+ Pow(radius, 2));
If instead of bringing this drawing process to a halt at step 4, if we were to continue it indefinitely for any number of steps of odd number n and even number n+1, we might describe it the procedure generally as follows:
Step 1: Draw A Circle
At The Point 0.0 ,0.0 ,0.0 with Radius 4.0. Step 2: Draw the next outer Square that circumscribes the Circle. Step 3: Draw the next outer Circle that circumscribes the last Square Step 4: Draw the next outer Square that circumscribes the last Circle. Step 5: Draw the next outer Circle that circumscribes the last Square Step 6: Draw the next outer Square that circumscribes the last Circle. .... Step n: Draw the next
outer Circle that circumscribes the last Square |
Within the last description we are beginning to recognize a kind of recurring relation. Rather that write down each step explicitly, we choose the shorthand n and n+1. We note that for every step n, we also have a step n+1. We can express this idea in terms of the variable n rather than the more brute force approach of explicitly writing down each step for whatever number of steps is needed. Our analysis of the relationship between the doubling circles and squares has yielded this shorthand. We have also identified that the radius resizing is the key to this recurring pattern of circle and square. Other constructions may reveal similar kinds of observations, where a series of similar forms can be constructed in a repeated sequence, where each step within the repeated sequence describes a general mathematical relation that is reused.
A doubling of circles of n = 19 steps
The For Loop
Lets now look at concise expression of the procedure for the doubling circles and squares. That is, lets formulate an expression in a GC script that more precisely expresses the pattern and key that we have discovered. Within the procedure below, we introduce a for loop. The integer variable named i corresponds to our earlier notions of step n and step n+1. Our first time through the loop, the integer variable i is set to the value of 1, and we draw the first inner circle in step 1 and the circumscribing square in step 2. Our first pass through the loop ends at the statement }.For our second pass through the loop, the integer variable i is incremented by 1 and is set to the value of 2. We now draw a circumscribing circle in step 3 and a circumscribing square in step 4. A fourth pass of through the loop would mean that counter would be set to the value of 4. This exceeds its predefined limit of 4 in the statement for i < n . The execution of the loop stops before a fourth pass can be executedand the program ends.
Note that we also introduce the use of a system function procedure Sqrt. The function Sqrt takes an expression within parenthesis and returns a value. The expression within the parenthesis is referred to as the argument to the function. More generally, a function call has the form ... functionname (argumentlist), where the argument list is a set of expressions each separated by a comma. The function Sqrt has single argument. The function Sqrt returns the square root of the argument. We will see more examples of function calls throughout this chapter, and return more formally to the nature of functions with arguements in a later chapter of this text.
function(){ //Draws the doubling of the circle, from Serlio, plate 3r, Book On Geometry //Describes a recurring relation with a for loop //define center coordinates of circle Point centerPoint = new Point(); double xval, yval, zval, radius, n; n = 4; radius = 4; xval = 0; yval = 0; zval = 0; centerPoint.ByCartesianCoordinates(baseCS, xval, yval, zval); //establish function to repeat operations 'n' times for (int i = 1; i < n; i++) { // STEP N: Start Drawing A Circle //draw circle using center and radius Circle circle1 = new Circle(this); circle1.ByCenterRadius(centerPoint, radius, baseCS.XYPlane); //initialize and save memory for points Point pointNE = new Point(); Point pointNW = new Point(); Point pointSW = new Point(); Point pointSE = new Point(); //locate the coordinates of the NE point xval = radius; yval = radius; zval = 0; //use coordinates to determine the NE point pointNE.ByCartesianCoordinates(baseCS, xval, yval, zval); //locate the coordinates of the NW point xval = -1 * radius; yval = radius; zval = 0; //use coords to determine the NW point pointNW.ByCartesianCoordinates(baseCS, xval, yval, zval); //locate the coordinates of the SW point xval = -1 * radius; yval = -1 * radius; zval = 0; //use coords to determine the SW point pointSW.ByCartesianCoordinates(baseCS, xval, yval, zval); //locate the coordinates of the SE point xval = radius; yval = -1 * radius; zval = 0; //use coords to determine the SE point pointSE.ByCartesianCoordinates(baseCS, xval, yval, zval); //STEP N+1: Draw the next outer Square that circumscribes the Circle Polygon square1 = new Polygon(this); square1.ByVertices({pointNE, pointNW, pointSW, pointSE}); //determine radius for second circle radius = Sqrt ((Pow (radius, 2)+ Pow(radius, 2))); } } |
In general, the for loop contains some integer variable to serve as the counter, the for statement, a "{" symbol to indicate the body of the for statment, a block of GC script statements to be executed, and then concludes with "}":
for (int i = 1; i < n; i++){
{
Note that if our program had included the statement (int i = 1; i <= n; i++) , we would have generated four pairs of circles and squares, since the loop would have included the case for i = 4;
for (int i = 1; i <= n; i++){ { |
With the <= statement, the resulting script would execute the loop four times and produce the following drawing:
Result of i<=n in the for loop
Iterative Figures
The series of Golden Rectangles illustrated in Chapter 1 also contains a repeated pattern where the key mathematical relation is to be found in the proportions of a golden rectangle. More generally, we can discover that a number of repeating patterns or relations exist within some forms found in architecture or nature. We might find it more convenient to say that this recurring pattern takes place. while some condition holds, or for a number of steps, or more simply that to reproduce a particular pattern, we need to do a process for a repeated number of times until a certain condition is achieved. Accordingly, the GC scripting language contains several kinds of iterative control structures to describe a procedure that occurs an indefinite number of times. We have just seen above the use of the for loop in the example above.. We will also review the while loop and the do ... while loop. To some extent each of these iterative control structures can be interchanged. However, they all exist to provide some flexibility in the way to describe a repetitive process. In the remaining part of this chapter, we will introduce these iterative control structures with respect to several kinds of curves.
A Circle
Lets imagine that we have a point P that revolves over time in plan about an origin 0. Lets also assume that through every angle of revolution, P remains at a constant distance from 0. Clearly sweeping P through 360 degrees would trace along the shape of a circle. We might approximate this result by determining the rotation of P for some constant angular increment, say every 10 degrees, and then connecting every successive location with a line segment. The lower the angular increment, the smaller the line segment length between locations of point P and therefore the greater the resolution of the circle. The higher the angular increment, the longer the line segment length between locations of point P, and the lower the resolution of the circle. This is demonstrated in the following chart.:
high resolution circle:
angular increment = 1 |
![]() |
angular increment = 20 | ![]() |
angular increment = 30 | ![]() |
Low resolution circle:
angular increment = 60 |
![]() |
The While Wend Loop
The following procedure makecircle uses a while loop to achieve this result. We use the relational operator <= which means less than or equal to as a means of controlling the execution of the loop. That is, the loop ends when the revolution of P around the origin sweeps greater than or equal to 360 degrees. We shall return to the use of relational operators at the end of this chapter. Note too that we make use of trigonometric functions Cos and Sin.
function(){ // Procedure makecircle to draw a circle as a series of line segments Point originPoint = new Point(); Point circlePoints= {}; //create empty list of points Polygon circlePoly = new Polygon (this); double degr, degrinc; double radius, radians; double distx, disty; double xval, yval, zval; int index; // initialize values xval = 0.0; yval = 0.0; zval = 0.0; originPoint.ByCartesianCoordinates(baseCS, xval, yval, zval); radius = 4; degr = 0; degrinc = 20; index = 0; // Initiate Drawing of Circle while number of degrees less than or equal to 360 while (degr <= 360.0) { // Determine x value and y value of Point distx = Cos(degr) * radius; disty = Sin(degr) * radius; Print("distx = " + distx + "\n"); Print("disty = " + disty + "\n"); // determine a point for the current value of distx and disty. xval = originPoint.X + distx; yval = originPoint.Y + disty; zval = originPoint.Z; Point curPoint = new Point(); curPoint.ByCartesianCoordinates(baseCS, xval, yval, zval); circlePoints[index] = curPoint; index = index + 1; // Increment the number of degrees of revolution of the point degr = degr + degrinc; } // Draw circle from Polygon segments circlePoly.ByVertices(circlePoints); } |
The mathematics of this program is based on simple trigonometry. Once we have determined the angle of revolution in degrees, we can use the Cos and Sin functions to determine the x coordinate value and y coordinate value of P.That is, from basic trigonometry we know that distance of the x coordinate of P from the originPoint is equal to the cosine of the angle of P times its distance radius from the originPoint. Within the GC script above, this observation is expressed as distx = cos (degr) * radius;. Similarly, the distance of the y coordinate of P is equal to sine of the angle of P times its distance radius from the origin.Within the GC script above, this observation is expressed as distx = Sin (eegr) * radius;. Finally, the location of point P is equal to the location of the originPoint plus its xdist and ydist values.This observation is expressed as xval = originPoint.x + distx, and yval = originPoint.y + disty. Since our circle is 2D, we also have that zval = originPoint.z.
Also note that we control the resolution of the circle by the value assigned to degrinc. The higher the value for degrinc, the fewer the points we will use to describe the circle, and therefore the lower the resolution of the circle. For relatively larger values, the variable degrinc has the impact of giving the circle a regular polygon representation. For a six sided polygon, you can use the assign the value of degrinc = 60, and for a four sided polygon, you can assign the value of degrinc=90. Thus, we can see that controlling the drawing of circle through this procedure lends insight into a number of related geometrical shapes.
As observed by D'Arcy Thompson in his treatise on Growth and Form, we can use a similar logic to look at Archimedes curve and also at the equiangular spiral or logarithmic curve. We can see an Archimedes curve in the shape of a anchor rope that is arranged in a tight spiral on the deck of a ship. As in the case of circle, we again might think of a point P that traces out the shape of this rope as it revolves around an origin point 0. Or, this form might also be found architecturally in the spiral plan for a ziggurat. Thompson noted that the description for logarithmic spiral may be understood in similar terms
"In the elementary mathematics of a spiral, we speak of the point of origin as the pole (O); a straight line having its extremity in the pole, and revolving around it, is called the radius vector; and a point (P) traveling along the radius vector under definite conditions of velocity, will then describe our spiral curve.
Of several mathematical curves who form and development may be so conceived, the two most important (and the only two with which we need deal) are those which are known as (1) the equable spiral, or spiral of Archimedes, and (2) the equiangular spiral or logarithmic curve". [Thompson, On Growth and Form, p. 175].
Archimedes Spiral
A small modification to the program makecircle converts it to a program to make an Archimedes spiral. In particular, we must add a radius increment to exist somewhere in the middle of our while ... wend loop. That is, the radius will lengthen at a constant rate for each degree that the point (P) travels around (O). To achieve this we might create a new variable radinc as a double at the beginning of the program. Before entering the main loop, we would initialize the value of radinc as radinc = 1.0. Since within the Archimedes spiral, point (P) may travel around (O) for a number of times, we might want to specify this in terms of a second new variable numrev and initialize its value to some desirable number of revolutions, say 5.
function(){ // Procedure to make an archimedes spiral Point originPoint = new Point(); Point spiralPoints= {}; //create empty list of points PolyLine archimedessprialPoly = new PolyLine (this); double degr, degrinc; double radius, radians; double distx, disty; double xval, yval, zval; double radinc, numrev; int index; // initialize values xval = 0.0; yval = 0.0; zval = 0.0; originPoint.ByCartesianCoordinates(baseCS, xval, yval, zval); radius = 4; radinc = 1.0; degr = 0; degrinc = 20; index = 0; numrev = 5.0; |
If we want the point (P) to spiral 5 times around the point (O), then we can continue to loop while the number of degrees is less than or equal to 5 revolutions, or 5 * 360. This is achieved with the statement While degr <= (numrev * 360). Within the body of the loop, we add the statement radius = radius + radinc to ensure that spiral increases with each turn of (P) around point (0). These two modifications to the original program makecirle are suggested in the excerpt below.
// Initiate Drawing of Circle while number of degrees less than the number of revolutions (times 360 degree) while (degr <= (360.0 * numrev)) { ... } |
These few changes to the original GC script will produce the following drawing of an Archimedes spiral.
the spiral of Archimedes at 5 numrev.
The equiangular or Logarithmic Curve
The expanding proportions of a nautilus shell might also be expressed as a loop. In contrast to the Archimedes spiral, the size of the curves increase at a higher rate of change with each increase in revolution angle. Or in other words, as D'Arcy Thompson observed, we still have point (P) traveling about point (O) as in the Archimedes curve. However, within the Archimedes curve, the point (P) moves outward at a uniform velocity along the radius from point (0) as the number of revolutions increase. Whereas, within the logarithmic spiral, the point (P) moves outward at an accelerating rate along the radius from point (0) as the number of revolutions increase.
A very simple adjustment to the GC script will effect this result. That is, we need to find a way to express the notion that an increase in the radius increments will also occur alongside that of an increase in the radius itself. We can therefore modify the following section of the initial program to add a new variable radaccel which will specify the acceleration rate of the radius.
function(){ // Procedure to make an accelerating spiral Point originPoint = new Point(); Point spiralPoints= {}; //create empty list of points PolyLine archimedessprialPoly = new PolyLine (this); double degr, degrinc; double radius, radians; double distx, disty; double xval, yval, zval; double radinc, numrev; double radaccel; int index; // initialize values xval = 0.0; yval = 0.0; zval = 0.0; originPoint.ByCartesianCoordinates(baseCS, xval, yval, zval); radius = 4; radinc = 1.0; radaccel = 2.0; degr = 0; degrinc = 20; index = 0; numrev = 5.0; |
We can now modify the main loop of the procedure such that rate of radius change is also increasing by adding the statement radinc = radinc + radaccel:
while (degr <= (360.0 * numrev)) { // Determine x value and y value of Point distx = Cos(degr) * radius; disty = Sin(degr) * radius; // determine a point for the current value of distx and disty. xval = originPoint.X + distx; yval = originPoint.Y + disty; zval = originPoint.Z; Point curPoint = new Point(); curPoint.ByCartesianCoordinates(baseCS, xval, yval, zval); spiralPoints[index] = curPoint; index = index + 1; radinc = radinc + radaccel; radius = radius + radinc; // Increment the number of degrees of revolution of the point degr = degr + degrinc; } |
For a value of radaccel = 2.0, we obtain the following drawing from running this program.
an increasing equiangular spiral at radaccel = 2 and numrev = 5
As was observed by Descartes, this increasing equiangular spiral has the appearance of a logarithmically expanding curve. A logarithm definition of this curve can also be developed more directly from our observations about point (P) rotating about point (O). We first need to revisit the Archimedes curve so as tie closely together the increasing size of the radius with the angle of (P) around (O)
Revisiting the Archimedes Curve
Yet another mathematical formulation of this Archimedes curve ties more closely together the values for the increasing size of the radius with the angle of (P) around (O). We now might observe with D'Arcy Thompson that each revolution point (P) about point (O) results in a radius = (OP). For an Archimedes curve, we have already noted that the radius is lengthened for each angular turn about point (O). We therefore can say that for some constant value coefa that the radius = degr * coefa, where the value of degr increases with each revolution about point (O) but the value of constant coefa remains the same. We can modify our initial program for the Archimedes curve so as to take this slightly modified observation into account by removing the variable radinc and introducing the variable coefa. The beginning of the program archimed now has the variable radinc removed and the variable coefa added:
function(){ // Procedure to make an archimedes spiral Point originPoint = new Point(); Point spiralPoints= {}; //create empty list of points PolyLine archimedessprialPoly = new PolyLine (this); double degr, degrinc; double radius; double distx, disty; double xval, yval, zval; double radinc, numrev; double coefa; int index; // initialize values xval = 0.0; yval = 0.0; zval = 0.0; originPoint.ByCartesianCoordinates(baseCS, xval, yval, zval); radius = 4; radinc = 1.0; degr = 0; degrinc = 20; index = 0; numrev = 5.0; coefa = 1.0; |
We can now modify the main loop of the Archimedes program as follows:
// Increment
the number of degrees of revolution and lengthen radius of the point degr = degr + degrinc; radius = coefa * degr; |
Running the Archimedes program modified in this way will give us a similar result as before.
Revisiting the equiangular or Logarithmic curve
Lets re-express the algebra of our procedure so that we use the log function itself to generate a logarithmic spiral. This requires that we use both the mathematics of logarithms and also use some of the properties of exponential numbers. The essential mathematics is applied here without a full treatment of the underlying proofs. Some readers may prefer to trust the underlying mathematics and skip the next three paragraph.
A little more behind the math is contained in this insert box for readers seeking a more complete background explanation: D'Arcy Thomson establishes the essential argument of the next two paragraphs in his treatise in On Growth and Form. The derivation is amplified below from the more abbreviated arguments in his original text. The third paragraph contains an additional transformation that allows us to more directly develop a corresponding computer graphics procedure. Note that this explanation uses the exponentiation symbol "^". For example, 2^3 = 8, or 3^3 = 27. We first need to consider definition of logarithms. In algebra we say that y is equal to the log of x base z if z^y gives us x. A constant number referred to as base e has special properties. The value of e is 2.71828183 when carried out to 8 decimal places. We can say that y is equal to the natural log of x if e^y gives us x. Or, it can be stated more simply that y is the log of x if e^y gives us x. Within the Archimedes spiral, we have seen in the example above that radius = degr * coefa . However, in the equiangular or logarithmic curve, we noted before that the radius increases exponentially. Therefore, the statement radius = coefa * degr needs to be adjusted. We can test the proposition that for any point (P) along the curve we would find that radius = coefa ^ degr for some constant coefa. That is, the radius of the point (P) is equal to some constant coefa taken to the exponent of degr. Taking the log of each side of the last expression we get log (radius) = log (coefa^degr). However, we know that logarithms have the property that log (coefa^degr) = degr * log (coefa). Taking the last two equations, we replace the left hand side of the first one with the right hand side of the second one and get that log (radius) = degr * log (coefa). Dividing both sides of this last equation by log (coefa), we now get degr = log (radius) / log (coefa). However, since coefa is a constant, then so is log (coefa). Lets define constanta as 1/log(coefa), and we can go further and reduce our equation to degr = log (radius) * constanta. This last equation gives meaning to Descartes particular observation that the angles of a point (P) revolving about point (O) are proportional to the logarithm of the radius. D'Arcy Thompson states that you can also understand the point (P) to accelerate as it moves outward from (O) in that it covers an increasing distance with each degree of turn. It is convenient in developing a procedure to be able to control our loop for some number of degrees. Therefore, we can use the equation, as discussed in the last paragraph, that degr = log (radius) * constanta, and transpose it so that the radius may be found from the number of degrees. That is, lets multiply both sides by 1/constanta so that the equation becomes degr/constanta = log (radius). If we refer to the definition of log (radius), then the last equation becomes radius = e^(degr/constanta). That is, we now have an equation in which the length of the radius can be determined on the basis of the degrees of revolution of point (P) about (O). We also have shown in the preceding paragraph how the log function is used in establishing this equation. |
animation showing
acceleration of point (P) around (O)
tracing out the curve of a nautilus shell
The Do Loop
Using our new equation radius = e^(degr/constanta), lets now at last rewrite the procedure for a generating an equiangular or logarithmic curve. In the GC Script languate, we would re-express radius = e^(degr/constanta) with the use of the Pow function. That is, we would write the equation as "radius = Pow (constante, (degr / constanta));" We will assign a value of 344.0 for constanta such that the size of the logarithmic curve matches the growth of a specific Nautilus shell (author's discovery). We will also use the third iteration technique of a do ... while until. This is the third kind of iteration technique that we will review in this chapter. The do ... while loop structure will repeat a block of code until reaching a condition. In this case, we want the looping to stop when we have exceeded revolving the point (P) around (0) for a number of degrees greater than (numrev * 360). This condition is satisfied when degr > (numrev * 360) as indicated in the procedure below.
function(){ // note that degrees
= log(radius) * constanta, radius = Pow (constante, (degr / constanta));
|
Running this new program within the CAD system for a constanta value of 344 traces out the growth of the nautilus shell.
The Logarithmic Curve of a Nautilus Shell for constanta value of 344.0
Relational Operators
Throughout this chapter we have used three kinds of iterative structures, the for loop, the while wend loop, and the do loop. Each kind of loop concludes when a particular condition is reached. Futhermore, some test is typically applied every time a loop is executed to see if the terminating condition has occurred. Often, terminating conditions are expressed with the use of a relational operator. The relational operator is used to compare two expressions . It produces a valued of True or False. This value typically has use in the context of a loop. A result of True will typically provide that the loop be repeated an additional cycle and a result of False would provide that the loop be discontinued. We have seen examples of this usage in the programs above. In the most recent example for the logarithmic curve, the relational operator was embedded within the statement Do { ... } degr <= (numrev * 360.0);. This means continue the loop repeats continuously while the value of the expression is True. If the variable numrev had been assigned the value of 2.0, then the loop would stop as soon as the value of the variable degre becomes greater than (2 * 360.0). That is, when the number of degrees is greater than 720.00, then the expression degr <= (numrev * 360.0) evaluates to be False (0), and that caused the termination of the loop.
We will be using relational operators routinely in the control of loops and within other contexts. The following table lists some common kinds of relational operators available in the GC scripting language.
Relational Operator | Purpose | Number Arguments | Example | Result |
== | is the left hand expressions equal to the right hand expression | 2 | 3.0 == (9.0 - 6.0) | True |
>= | is the left hand expression greater than or equal to the right hand expression | 2 | 3.0 >= (9.0 - 6.0) | True |
> | is the left hand expression greater than the right hand expression | 2 | 3.0 > (9.0 - 6.0) | False |
<= | is the left hand expression less than or equal to right hand expression | 2 | 3.0 <= (9.0 - 6.0) | True |
< | is the left hand expression less than the right hand expression | 2 | 3.0 < (9.0 - 6.0) | False |
!= | is the left hand expression not equal to the right hand expression | 2 | 3.0 != (9.0 - 6.0) | False |
Loops may also be controlled by other kinds of operators. Logical Operators are also used often. We will return to the discussion of logical operators, however, in a later chapter of the text.
Summary
Within this chapter we have examined the nature of certain geometrical compositions where recurring relationships among more primitive parts are in evidence. The discovery of these recurring relationships allows us to think of these geometrical compositions from a perspective that takes into account broader patterns and not just individual elements. The GC scriptinglanguage provides for an analogous means to articulate the recurring relations as a procedure. In particular, we have examined the use of loops to describe Serlio's doubling circles, an Archimedes curve, and have re-visited D'Arcy Thompson's logarithmic spiral applied to a nautilus shell. We have seen three kinds of loops structures provided within the GC scritping language (1) for ... , (2) while ... , and (3) do ... loop. These structures are for the most part interchangeable,. However, one kind of structure may may be at times provide for a more convenion expression of the variables, values or logic related to a particular loop.
Within the next chapter, we will begin to look at other ways of structuring a graphics composition. Whereas in this chapter we looked at recurring relations within graphic compositions, in the next chapter we will look at the higher level organization of different kinds of recurring relations that may also be evident within graphic compositions.
Assignment 4: Procedures that express recurring relations