boxes3.mws

MathClass Lesson 1:

Blocks and Bricks

Section 3: Building a Block Factory

Creating Maple Procedures

If we are to construct more complex figures out of cubes and manipulate them in more interesting ways we need a more efficient means of producing the rectangular boxes with which to build them. It would be nice if there were a Maple word which instructed the program to make, say, a cube of side 1 and place it at a location of our choice. In the previous chapter we did all of the work that such a word would do. We constructed the basic cube and placed it in the desired location by specifying a "shift". The steps to create a simple, colorless cube might be:

> restart:

> front:=[v1,v2,v3,v4]:
back:=[v5,v6,v7,v8]:
left:=[v4,v8,v5,v1]:
right:=[v3,v2,v6,v7]:
bottom:=[v3,v4,v8,v7]:

top:=[v1,v2,v6,v5]:
box:=[front,back,left,right,top,bottom]:

> shift:=[0,0,0]:

> v1:=[0,0,0]+shift: v2:=[1,0,0]+shift: v3:= [1,1,0]+shift: v4:=[0,1,0]+shift: v5:=[0,0,1]+shift: v6:=[1,0,1]+shift: v7:=[1,1,1]+shift: v8:=[0,1,1]+shift:

> cube0:= plots[polygonplot3d](box):
cube0;

[Maple Plot]

If we wanted the cube placed at any particular place in space all we have to do is change the value of "shift". If we wanted to retain the previous cube then instead of simply having plots[polygonplot3d] immediately draw the picture we assigned the plot structucture generated to a word, say "cube1". Then we could change the shift and the name, say to "cube2" and have plots[display] show us our cubes separately or individually as we wish.

What we would really like to do is have a Maple word, say "cube" which would take in the shift and produce the plot structure for the corresponding cube. We want the command "cube([0,0,0])" to produce the results of the previous set of commands and would want "cube([0,0,1])" to produce the results of simply changing "shift" to "[0,0,1]" in the same list of commands. That is, all we want is a way to vary the value of "shift " in this set of commands. Maple does this with procedures . The form of a Maple procedure is simple:

ProcedureName:= proc(input_variable)

Maple commands in which "input_variable" is treated as input.

end;

For instance suppose we want a Maple word which always returns a picture of a unit square of whichever color we specify. We need a choice for this word, the ProcedureName. Any choice will work provided its not "reserved" by Maple. For instance we might choose "colorsquare". We need a name for the procedure variable. Since we are going to vary color we choose something like "clr" since we have seen that "color" is a word already defined in Maple. Finally we need to know the Maple word which will produce a square of a given color. We know that the following will work :

plots[polygonplot3d]([[0,0,0],[1,0,0],[1,1,0],[0,1,0]], color=red);

Thus following the above format we create a new word:

> colorsquare:=proc(clr)
plots[polygonplot3d]([[0,0,0],[1,0,0],[1,1,0],[0,1,0]], color=clr);
end:

We can test the work out right away.

> colorsquare(blue);

[Maple Plot]

Creating our "cube" word is no more difficult and is done essentially by cutting and pasting the code that does one general enough case, changing the specific values in the code to the variable quantities for the procedure and "wrapping" this in the "proc()...end wrapper". Doing this with the instructions that made "cube0" whe would assemble

cube:=proc(shift)
"instructions for making cube 0"

end;

> cube:=proc(shift)
local v1, v2, v3, v4, v5, v6, v7, v8, front, back, left, right, bottom, top, box;

v1:=[0,0,0]+shift:
v2:=[1,0,0]+shift:
v3:= [1,1,0]+shift:
v4:=[0,1,0]+shift:
v5:=[0,0,1]+shift:
v6:=[1,0,1]+shift:
v7:=[1,1,1]+shift:
v8:=[0,1,1]+shift:

front:=[v1,v2,v3,v4]:
back:=[v5,v6,v7,v8]:
left:=[v4,v8,v5,v1]:
right:=[v3,v2,v6,v7]:
bottom:=[v3,v4,v8,v7]:
top:=[v1,v2,v6,v5]:

box:=[front,back,left,right,top,bottom]:

plots[polygonplot3d](box);
end:

For the moment pay no attention to the "warning" messages, we will clean that up shortly. Right now what we need to see is that we do indeed have a "cube" word. The idea is always to get something working and improve it.

> joe:=cube([1,2,4]): sam:=cube([1,0,1]): sally:=cube([1,1,1]): joesamsally:=plots[display]([joe,sam,sally],color=red,scaling=constrained):
joesamsally;

[Maple Plot]

Now that we have a basic version of "cube" we can add features. Suppose we want to specify the style and color of the cube as well as the shift. This is easy as Maple procedures are not restricted to a single variable. It is a good idea to make a single improvement at a time, though. This makes finding errors much easier. Lets specify the style first. All we need to do is copy the code over. We don't go back and change our only copy of a piece of working code . We copy the working version, paste it in and (ususally) change the name at least temporarily.

> tempcube := proc (shift)
local v1, v2, v3, v4, v5, v6, v7, v8, front, back, left, right, bottom, top, box;
v1 := [0, 0, 0]+shift;
v2 := [1, 0, 0]+shift;
v3 := [1, 1, 0]+shift;
v4 := [0, 1, 0]+shift;
v5 := [0, 0, 1]+shift;
v6 := [1, 0, 1]+shift;
v7 := [1, 1, 1]+shift;
v8 := [0, 1, 1]+shift;
front := [v1, v2, v3, v4];
back := [v5, v6, v7, v8];
left := [v4, v8, v5, v1];
right := [v3, v2, v6, v7];
bottom := [v3, v4, v8, v7];
top := [v1, v2, v6, v5];
box := [front, back, left, right, top, bottom];
plots[polygonplot3d](box);
end:

This is, of course simply our original code with a different name. Now we modify it to take both a shift and a color. We have indicated the changes in upper case in the following copy. In this case we simply add a variable "clr" and the option color=clr in the plots[polygonplot3d] command.

> tempcube1 := proc (shift, clr)
local v1, v2, v3, v4, v5, v6, v7, v8, front, back, left, right, bottom, top, box;
v1 := [0, 0, 0]+shift;
v2 := [1, 0, 0]+shift;
v3 := [1, 1, 0]+shift;
v4 := [0, 1, 0]+shift;
v5 := [0, 0, 1]+shift;
v6 := [1, 0, 1]+shift;
v7 := [1, 1, 1]+shift;
v8 := [0, 1, 1]+shift;

front := [v1, v2, v3, v4];
back := [v5, v6, v7, v8];
left := [v4, v8, v5, v1];
right := [v3, v2, v6, v7];
bottom := [v3, v4, v8, v7];
top := [v1, v2, v6, v5];

box := [front, back, left, right, top, bottom];

plots[polygonplot3d](box,color=clr)
end:

Now test this change right away.

> tempcube1([0,0,0],red);

[Maple Plot]

Now we can go another step and change the style

> tempcube2 := proc (shift,clr,styl)
local v1, v2, v3, v4, v5, v6, v7, v8, front, back, left, right, bottom, top, box;
v1 := [0, 0, 0]+shift;
v2 := [1, 0, 0]+shift;
v3 := [1, 1, 0]+shift;
v4 := [0, 1, 0]+shift;
v5 := [0, 0, 1]+shift;
v6 := [1, 0, 1]+shift;
v7 := [1, 1, 1]+shift;
v8 := [0, 1, 1]+shift;

front := [v1, v2, v3, v4];
back := [v5, v6, v7, v8];
left := [v4, v8, v5, v1];
right := [v3, v2, v6, v7];
bottom := [v3, v4, v8, v7];
top := [v1, v2, v6, v5];

box := [front, back, left, right, top, bottom];

plots[polygonplot3d](box,color=clr,style=styl )

end:

> tempcube2([2,1,3], blue, patch);

[Maple Plot]

Now we can play with colored cubes:

> cube1:=tempcube2([0,0,0],blue,patch):
cube2:=tempcube2([1,0,0],yellow ,patch): cube3:=tempcube2([2,0,0],tan ,patch):cube4:=tempcube2([1/2,0,1],green ,patch):cube5:=tempcube2([3/2,0,1],red ,patch):cube6:=tempcube2([1,0,2],red,patch):

> sixcubes:=plots[display]([cube1,cube2,cube3, cube4,cube5,cube6 ],scaling=constrained):
sixcubes;

[Maple Plot]

EXERCISE 1: Modify the tempcube2 procedure to make a word which makes cubes which have white tops and bottoms and whose sides are any color we specify .

Another Example of how to "procedurize" a sequence of commands.

It is very important to learn the process of organizing sequences of Maple commands which solve a specific problem into a procedure for doing a general problem of that form. For example. The following command sequence calculates the equation of the line though the two points [1,3] and [-5,12] .

> eqn:= y=slope*x+yintercept;

eqn := y = slope*x+yintercept

> slope:= (12 - 3)/(-5 - 1);

slope := -3/2

> yintercept:=3 - slope*1;

yintercept := 9/2

> eqn;

y = -3/2*x+9/2

We want to modify this to take in the x and y coordinates of any two points [x1,y1] and [x2,y2] and to return the equation of the line through them. Once we see that we should think of [1,3] as the particular [x1,y1] and [-5,12] as the particular [x2,y2] we can readily wrap this into a procedure with a name such as "lineequ". Note that we are ignoring for the moment the possibility that x1=x2 in which case Maple will complain about division by zero. We'll learn to take care of such things later .

> lineequ:=proc(x1,y1,x2,y2)
local slope, intercept, eqn;

eqn:= y=slope*x+intercept;
slope:= (y2 - y1)/(x2 - x1);
intercept:= y1 - slope*x1;

y=slope*x+intercept;
end:

>

> lineequ( 1,3, -5,12);

y = -3/2*x+9/2

>

EXERCISE 2: The Maple commands below find the point of intersection of two specific lines in the plane from their equations, each of the form y=mx+b. Make this code into a procedure intersect(L1,L2)) which finds the point of intersection of the lines with equations L1 and L2. (remark: We are not worrying at this point about such niceties as whether the two lines are parallel or not. We will learn to check for this sort of thing later).
Test your word on several lines
.

> L1:=y=3*x-2;

L1 := y = 3*x-2

> L2:=y=7*x-5;

L2 := y = 7*x-5

> ans:=solve({L1,L2},{x,y});

ans := {y = 1/4, x = 3/4}

>

> subs(ans,[x,y]);

[3/4, 1/4]

>


EXERCISE 3: The following Maple command adds up the squares of the first 4781 positive integers. Adapt it to make a Maple word addpowers(n,m) which returns the sum of the nth powers of the integers from 1 to m. Use your word to answer the following question: Which is larger, the sum of the 4th powers of the first 100 positive integers, or the sum of the third powers of the first 300 integers?

> sum(i^2,i=1..4781);

36439400291

>

Example:

One often finds colored cubes as children's toys and these often have letters painted on them. Lets investigate the possibility of making a white cube with a blue "K" on one face. The white cube is no problem. We need to make the "K". We only know how to make CONVEX polygons so we must assemble our "K" from components of that type.

[Maple OLE 2.0 Object]
This one is made of the polygons A,B, and C. All we need to do is draw something like this on a piece of graph paper, read off the coordinates of the vertices, make up each of the polygons and put them together.

> A:=[[1/10,0,1/10],[1/10,0,9/10],[3/10,0,9/10],[3/10,0,1/10]];

A := [[1/10, 0, 1/10], [1/10, 0, 9/10], [3/10, 0, 9...

>

> B:=[[3/10,0,4/10],[3/10,0,6/10],[6/10,0,9/10],[9/10,0,9/10]];

B := [[3/10, 0, 2/5], [3/10, 0, 3/5], [3/5, 0, 9/10...

> C:=[[4/10,0,5/10],[6/10,0,6/10],[9/10,0,1/10],[7/10,0,1/10]];

C := [[2/5, 0, 1/2], [3/5, 0, 3/5], [9/10, 0, 1/10]...

> K:=plots[polygonplot3d]([A,B,C],color=blue,style=patch):
whitecube:=tempcube2([0,0,0],white,patch);

whitecube := INTERFACE_PLOT3D(POLYGONS([[0., 0., 0....
whitecube := INTERFACE_PLOT3D(POLYGONS([[0., 0., 0....
whitecube := INTERFACE_PLOT3D(POLYGONS([[0., 0., 0....

> Kcube:=plots[display]([K,whitecube]):
Kcube;

[Maple Plot]

I t may be necessary to rotate the cube (use the mouse) in order to see the "K".

There are two problems here. The first is a very sloppy "K" which results from inaccurate reading of coordinates from a hastily drawn graph. This can be partially addressed by more careful graphing. The second problem is that some views of the cube show a two-toned "K". This is what happens when two patch-style pictures are in contact. Polygons are made of colored triangles and the computer is not able to resolve which is "above" the other. The solution is to move them slightly apart. In this case its we might have the "K" as being slightly raised above the surface of the cube. That just means altering the definition of K

> A:=[[1/10,-.01,1/10],[1/10,-.01,9/10],[3/10,-.01,9/10],[3/10,-.01,1/10]];

A := [[1/10, -.1e-1, 1/10], [1/10, -.1e-1, 9/10], [...

> B:=[[3/10,-.01,4/10],[3/10,-.01,6/10],[6/10,-.01,9/10],[9/10,-.01,9/10]];

B := [[3/10, -.1e-1, 2/5], [3/10, -.1e-1, 3/5], [3/...

> C:=[[4/10,-.01,5/10],[6/10,-.01,6/10],[9/10,-.01,1/10],[7/10,-.01,1/10]];

C := [[2/5, -.1e-1, 1/2], [3/5, -.1e-1, 3/5], [9/10...

> K:=plots[polygonplot3d]([A,B,C],color=blue,style=patch):
whitecube:=tempcube2([0,0,0],white,patch);

whitecube := INTERFACE_PLOT3D(POLYGONS([[0., 0., 0....
whitecube := INTERFACE_PLOT3D(POLYGONS([[0., 0., 0....
whitecube := INTERFACE_PLOT3D(POLYGONS([[0., 0., 0....

> Kcube:=plots[display]([K,whitecube]):
Kcube;

[Maple Plot]

This solves the

Lets add a red "K" to the other side

> A1:=[[1/10,1.01,1/10],[1/10,1.01,9/10],[3/10,1.01,9/10],[3/10,1.01,1/10]];

A1 := [[1/10, 1.01, 1/10], [1/10, 1.01, 9/10], [3/1...

> B1:=[[3/10,1.01,4/10],[3/10,1.01,6/10],[6/10,1.01,9/10],[9/10,1.01,9/10]];

B1 := [[3/10, 1.01, 2/5], [3/10, 1.01, 3/5], [3/5, ...

> C1:=[[4/10,1.01,5/10],[6/10,1.01,6/10],[9/10,1.01,1/10],[7/10,1.01,1/10]];

C1 := [[2/5, 1.01, 1/2], [3/5, 1.01, 3/5], [9/10, 1...

> K1:=plots[polygonplot3d]([A1,B1,C1],color=red,style=patch):

> plots[display]([K,whitecube,K1]);

[Maple Plot]

>

>

EXERCISE : Improve the "Kcube" by creating a "K" such that there is no guesswork in the coordinates of its components .

[Maple OLE 2.0 Object]

>

>

>

EXERCISE : Change the "Kcube" so that there is a "K" on each face.
EXERCISE : Make a yellow block with one the letters A,B,C,D,E,F on each face .

EXERCISE : Give each of the letters in the previous problem a different color.
EXERCISE : Make the block in the previous problem appear to be made of a transparent material with the colored letters painted on its faees.
EXERCISE : Make a stack of alphabet blocks that present your initials.