Eisenberg: Favorite linear algebra projects
Worldwide Mathematica Conference • Chicago 1998

Project:  Stretching and spinning a cat

This project deals with transformations of the plane and their visualization through computer graphics.

Mathematica background

Transformations and objects for examples

We shall use a triangle as an example.  First we form the list pairs of pairs of coordinates of its vertices and the Line (that is, broken line) primitive graphics object:

\(pairs\  = 
      \ {{\(-1\), 1\ }, \ {0.25, \ \(-1\)}, 
        \ {0.75, \ 0.65}, {\(-1\), 1\ }\ }; 
edges\  = \ Line[pairs]\)

To see the triangle's three edges, form a Graphics object...

Graphics[edges]

... and then Show that Graphics object:

Show[Graphics[edges]];

The triangle's vertices will constitute a list of Point primitive graphics objects:

vertices  =  Map[Point,  pairs]

Here's the edges and vertices together...

Show[Graphics[{edges,  vertices}]];

... but it's rather hard to see the vertices because they are so small.  So we enlarge the points by using the PointSize graphics directive.  (The parameter to PointSize is expressed as a fraction of the graphics image width.)

triangle  =  {edges, PointSize[0.025],  vertices}

Now we can see vertices as well as edges:

Show[Graphics[triangle]];

Below we'll use two transformations of the plane—reflection across the vertical axis and translation by a specified vector:

reflect[p_]  := 
         {-p[[1]],  
        p[[2]]}trans[p_,  a_]  :=  p  +  a

For example:

reflect[{ 0.75,  0.65}]

trans[ {0.75,  0.65},  {1,  2}]

Graphics utility provided to students

The function displayFigure displays graphics objects.  (The aauxiliary function makeFigure forms a graphics object and associates some display options with it.)

\(makeFigure[objects_, \ low_:\  - 1, \ high_:  1]\  := \ 	
	
      Graphics[objects, \ 	
        PlotRange\  -> \ {{low, \ high}, \ {low, \ high}}, 
		\ 
        AspectRatio\  -> \ Automatic, \ Axes\  -> \ True]
\)displayFigure[objects_,  low_:  - 1,  high_:  1]  :=  
      Show[makeFigure[objects,  low,  high]]

Example:

displayFigure[triangle];

The functions both allow optional second and third arguments to specify the lower and upper bounds of the plot window.  For example:

displayFigure[triangle,  -2,  2];

Transformation utilities

The function image applies its first argument T (intended to be a plane transformation) to all the points of the objects constituting its second argument.  (The auxiliary function PointQ tests whether its argument is a list of two numbers.)

PointQ[p_] := VectorQ[p, NumberQ] && Length[p] == 2image[T_,  object_]  :=  object  /.  pt_?PointQ  :>  T[pt]

Here's our example again...

triangle

... and its image under the transformation reflect:

image[reflect,  triangle]

displayFigure[image[reflect,  triangle]]

displayFigure[reflect~image~triangle];

The Notation package allows us to use the symbol ∘ to denote function composition, just as in traditional mathematical notation.

<< Utilities`Notation`

InfixNotation[∘,Composition]

For example:

stretch[v_]  :=  1.5 vstretch[{1,  2}]reflect[%](reflect∘stretch)[{1, 2}]

Exercises

Exercise 1. Design and display the face of a cat.

More precisely:  Create a graphics object consisting entirely of line segments that, when displayed, looks like a cat's face.  Locate the face in the first quadrant.

In an actual course, the students would do this, perhaps by designing the face on graph paper and then constructing the Mathematica object using the coordinates on their paper.  Or they could do something sophisticated like the following.  (I first centered the face at the origin in order to exploit symmetry, obtaining an urCat.  Then I shrank the urCat to a suitable size and finally translatedthe result into the first quadrant.

facexy[j_]  :=  
      0.75 { Cos[2 π (j/20)],  0.88 Sin[2  π (j/20)]};

\(outline\  = \ Line[\ Table[facexy[j], \ {j, \ 0, \ 20}]]; 

    mouth\  = \ 
      Line[{{0, \ \(-0.25\)}, \ {\(-0.153\), \ \(-0.44\)}, 
          \ {0.153, \ \(-0.44\)}, {0, \(-\ 0.25\)}\ }]; 

    rightEar\  = \ Line[{facexy[2], \ {0.657, \ 1.0}, facexy[4]}]; 

    leftEar\  = \ reflect\ ~image~\ rightEar; 

    ears\  = \ {rightEar, \ leftEar}; 

    rightEye\  = \ 
      Line[{{0.123, \ 0.25 - 0.125}, \ {0.464, \ 0.205}, \ {0.464, \ 0.045}, 
          \ {0.123, \ 0.25 - 0.125}}]; 

    leftEye\  = \ reflect\ ~image~\ rightEye; 

    eyes\  = \ {rightEye, \ leftEye}; 

    spray[source_, \ targets_]\  := \ 
      MapThread[Line, \ Outer[List, \ {source}, \ targets, \ 1], \ 1]\)\(rightWhiskers\  = \ 
      spray[{0.125, \ \(-0.2\)}, 
        \ {\ {0.88, \ 0.07}, \ \ {0.932, \ \(-0.151\)}, 
          \ \ {0.88, \ \(-0.34\)}}]; 

    leftWhiskers\  = \ reflect\ ~image~\ rightWhiskers; 

    whiskers\  = \ Join[rightWhiskers, \ leftWhiskers]; 

    urCat\  = \ Join[{outline, \ mouth}, ears, \ eyes, \ whiskers]; \)

displayFigure[urCat];

shrink[v_]  :=  0.5 v\(smallCat\  = \ shrink\ ~image~\ urCat; 

    cat\  = \ image[trans[#, \ {0.5, \ 0.5}]&, \ smallCat]; \)

So here at last is our cat.

displayFigure[cat];

Exercise 2. Find and plot the image of the face under the following transformations of the plane:

Reflection M across the vertical axis

Translation T by the vector {1,  -1}

Rotation R by the angle π/6

Exercise 3. Why does "connecting the dots" of the face vertices' images correctly produce the image of the entire face under such transformations?

When Mathematica plots a line segment such as  Line[{0,1}, {2,3}], it creates the the two points given as endpoints—the "dots"— and then in effect "connects the dots", that is, draws a line segment between the two points.  And similarly for a broken line with several vertices.

The function image merely replaces each coordinate pair in the graphics object by the image of that pair under the transfomation.  For example:

image[F,  Line[{0, 1},  {2, 3}]]

Hence when Mathematica displays the graphics from an expression of the form displayFigure[F ~image~ object], it calculates the images under F of all the vertices in the object and then connects the images according to the way the coresponding original vertices were connected.  The question, then, is why this is legitimate—is Mathematica correctly finding the images of all the intermediate points on the line segments constituting the original object?

The following example—which uses the function rotate defined in the preceding exercise—may help to visualize the issue.

ptsFromLine[obj_]  :=  
      (obj  /.   pt_?PointQ  :>  Point[pt])[[1
        ]]pointsFromLines[obj_]  :=  Flatten[Map[ptsFromLine,  obj]]bigPoints[obj_]  :=  {PointSize[0.02],  pointsFromLines[obj]}

displayFigure[Join[cat, bigPoints[cat]],  -1.25,  1.25];

\(mirrorCat\  = \ reflect\ ~image~\ cat; 

    displayFigure[Join[mirrorCat, bigPoints[mirrorCat]], \ \(-1.25\), \ 
      1.25]; \)

Exercise 4. Find and plot the image of the face under the following compositions in each of their two orders.
What do the results suggest?

Reflection M and translation T (as above)

Reflection M and dilation D by the factor 0.75

Exercise 5. Plot the image of the face under the transformation \(TraditionalForm
      \`T : \ ℝ\^\(2\ \) → \ \ 
          ℝ\^\(2\ \)\) defined by
\(TraditionalForm
      \`T(x\_1, \ x\_2)\  = \ 
        \((x\_1\  + \ x\_2, \ x\_1\  + \ 2\ x\_2)\)\).
Describe the effect of T geometrically.
Repeat  for (T^2)  =  T ∘ T.
Is T a rigid motion?  Why or why not?  (Give both visual and computational reasons.)

The next two exercises were suggested by similar ones in materials by Frank Wattenberg at either of the following Web sites:
	http://www.math.montana.edu/~frankw/ccp/multiworld/topic.htm
	http://umastr1.math.umass.edu/~frankw/ccp/multiworld/topic.htm

Exercise 6. Make an animation showing the cat's face moving from its original position to its image under T.

Exercise 7. Make an animation showing the cat's face spinning around the origin.
(First make the cat smaller and center it at {2,  0}.)

First, spin the cat by rotating the center of its face around the circle.

Spin the cat again, but keep its head always upright!

To main notebook