f@c transfor.texi

@c This file is part of the 3DLDF User and Reference Manual.
@c Copyright (C) 2003, 2004 Laurence D. Finston 
@c See the section "GNU Free Documentation License" in the file 
@c fdl.texi for copying conditions.

@c $Id: transfor.texi,v 1.5 2004/01/12 18:43:23 lfinsto1 Exp lfinsto1 $
  
@node Transform Reference, Label Reference, Shape Reference, Top
@chapter Transform Reference

@tindex Transform
Class @code{Transform} is defined in @file{transfor.web}.
@code{Point} is a @code{friend} of @code{Transform}.

@menu
* Transform Data Members::      
* Transform Global Variables and Constants::  
* Transform Constructors ::     
* Transform Operators::         
* Matrix Inversion::            
* Setting Values Transforms::   
* Querying Transforms::         
* Returning Information for Transforms::  
* Showing Transforms::          
* Affine Transformations for Transforms::  
* Alignment with an Axis for Transforms::  
* Resetting Transforms::        
* Cleaning Transforms::         
@end menu

@node Transform Data Members, Transform Global Variables and Constants, Transform Reference, Transform Reference
@section Data Members

@deftypevr {Private variable} Matrix matrix
A @BYM{4,4}
matrix of @code{real} representing the actual transformation matrix.
@end deftypevr 

@node Transform Global Variables and Constants, Transform Constructors , Transform Data Members, Transform Reference
@section Global Variables and Constants

@deftypevar Transform user_transform
Currently has no function.  It is intended to be used for transforming
the coordinates of @code{Points} between the world coordinate system
(WCS) and a user coordinate system (UCS), when routines for managing
user coordinate systems are implemented.
@end deftypevar


@deftypevr {Constant} {@code{const} Transform} INVALID_TRANSFORM
Every member of @code{matrix} in @code{INVALID_TRANSFORM} is 
equal to @code{INVALID_REAL}.
@end deftypevr

@deftypevr Constant {@code{const} Transform} IDENTITY_TRANSFORM
Homogeneous coordinates and @code{Transforms} are unchanged by
multiplication with @code{IDENTITY_TRANSFORM}.
@code{matrix} is an identity matrix:
@c
@iftex
@tex
$$\pmatrix{1&0&0&0\cr
           0&1&0&0\cr
           0&0&1&0\cr
           0&0&0&1\cr}$$
@end tex
@end iftex
@c
@ifnottex
@display 
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
@end display
@end ifnottex
@c
@c   
@xref{Transforms}.
@end deftypevr

@node Transform Constructors , Transform Operators, Transform Global Variables and Constants, Transform Reference
@section Constructors 

@deftypefn {Default constructor} void Transform (void)
Creates a @code{Transform} containing the identity matrix.
@end deftypefn

@deftypefn Constructor void Transform (real @var{r})
Creates a @code{Transform} and sets all of the elements of @var{matrix}
to @var{r}.  Currently, this
constructor is never used, but who knows? Maybe someday it will be
useful for something.
@end deftypefn

@deftypefn Constructor void Transform (real @var{r0_0}, real @var{r0_1}, real @var{r2}, real @var{r0_2}, real @var{r0_3}, real @var{r1_0},  @var{real r1_1},  real @var{r1_2},  @var{real r1_3}, real @var{r2_0}, real @var{r2_1}, real @var{r2_2}, real @var{r2_3}, real @var{r3_0}, real @var{r3_1}, real @var{r3_2}, real @var{r3_3})
Each of the sixteen @code{real} arguments is
assigned to the corresponding element of @var{matrix}:  
@code{matrix[0][0] = r0_0}, @code{matrix[0][1] = r0_1}, etc.
Useful for specifying a transformation matrix completely.
@end deftypefn

@node Transform Operators, Matrix Inversion, Transform Constructors , Transform Reference
@section Operators

@deftypefn {Assignment operator} Transform operator= ({const Transform&} @var{t})
Sets @var{*this} to @var{t} and returns @var{t}.  Returning @var{*this}
would, of course, have exactly the same effect.
@end deftypefn


@deftypefn Operator real operator*= (real @var{r})
Multiplication with assignment by a scalar.
This operator multiplies each element 
@math{E}
of @code{matrix} by
the scalar @var{r}.
The return value is @code{r}.  This makes it possible to
chain invocations of this function:
@c
@iftex
@tex
For $a_x, b_x, c_x, \ldots, p_x \in {\REAL}$,
$x \in {\NATURAL}$
@end tex
@end iftex
@ifnottex
For @math{a_x}, @math{b_x}, @math{c_x}, @dots{}, @math{p_x} in @REAL{},
@math{x} in @NATURAL{}
@end ifnottex

@example
Transform T0(a_0, b_0, c_0, d_0,
             e_0, f_0, g_0, h_0,
             i_0, j_0, k_0 l_0,
             m_0, n_0, o_0, p_0);
Transform T1(a_1, b_1, c_1, d_1,
             e_1, f_1, g_1, h_1,
             i_1, j_1, k_1 l_1,
             m_1, n_1, o_1, p_1);
Transform T2(a_2, b_2, c_2, d_2,
             e_2, f_2, g_2, h_2,
             i_2, j_2, k_2 l_2,
             m_2, n_2, o_2, p_2);
real r = 5;
@end example

@c


Let @math{M_0}, @math{M_1}, and @math{M_2} stand for 
@code{T0.matrix}, @code{T1.matrix}, and @code{T2.matrix}
respectively:

@iftex
@tex
\bigskip
\line{\hss
   $M_0 =\pmatrix{a_0&b_0&c_0&d_0\cr
                  e_0&f_0&g_0&h_0\cr
                  i_0&j_0&k_0&l_0\cr
                  m_0&m_0&o_0&p_0\cr}$\hfil
   $M_1 =\pmatrix{a_1&b_1&c_1&d_1\cr
                  e_1&f_1&g_1&h_1\cr
                  i_1&j_1&k_1&l_1\cr
                  m_1&m_1&o_1&p_1\cr}$\hss}
\bigskip
\line{\hfil $M_2 =\pmatrix{a_2&b_2&c_2&d_2\cr
                        e_2&f_2&g_2&h_2\cr
                        i_2&j_2&k_2&l_2\cr
                        m_2&m_2&o_2&p_2\cr}$\hfil}
\bigskip
@end tex
@end iftex
@c
@ifnottex
@display 
@math{M_0 =
a_0 b_0 c_0 d_0
e_0 f_0 g_0 h_0
i_0 j_0 k_0 l_0
m_0 m_0 o_0 p_0}

@math{M_1 =
a_1 b_1 c_1 d_1
e_1 f_1 g_1 h_1
i_1 j_1 k_1 l_1
m_1 m_1 o_1 p_1}

@math{M_2 =
a_2 b_2 c_2 d_2
e_2 f_2 g_2 h_2
i_2 j_2 k_2 l_2
m_2 m_2 o_2 p_2}
@c
@end display
@end ifnottex

@example
T0 *= T1 *= T2 *= r;
@end example

Now,@*
@c
@iftex
@tex
\bigskip

\setbox0=\hbox{$ M_0 =\pmatrix{5a_0&5b_0&5c_0&5d_0\cr
                        5e_0&5f_0&5g_0&5h_0\cr
                        5i_0&5j_0&5k_0&5l_0\cr
                        5m_0&5m_0&5o_0&5p_0\cr}$}
\setbox1=\hbox{$M_1 =\pmatrix{5a_1&5b_1&5c_1&5d_1\cr
                        5e_1&5f_1&5g_1&5h_1\cr
                        5i_1&5j_1&5k_1&5l_1\cr
                        5m_1&5m_1&5o_1&5p_1\cr}$}
\bigskip
\line{\hss\unhbox0\hfil\unhbox1\hss}

\bigskip
\line{\hfil $M_2 =\pmatrix{5a_2&5b_2&5c_2&5d_2\cr
                       5e_2&5f_2&5g_2&5h_2\cr
                        5i_2&5j_2&5k_2&5l_2\cr
                        5m_2&5m_2&5o_2&5p_2\cr}$\hfil}
\bigskip
@end tex
@end iftex
@c
@ifnottex
@display
@math{M_0 =
5a_0 5b_0 5c_0 5d_0
5e_0 5f_0 5g_0 5h_0
5i_0 5j_0 5k_0 5l_0
5m_0 5m_0 5o_0 5p_0}

@math{M_1 =
5a_1 5b_1 5c_1 5d_1
5e_1 5f_1 5g_1 5h_1
5i_1 5j_1 5k_1 5l_1
5m_1 5m_1 5o_1 5p_1}

@math{M_2 =
5a_2 5b_2 5c_2 5d_2
5e_2 5f_2 5g_2 5h_2
5i_2 5j_2 5k_2 5l_2
5m_2 5m_2 5o_2 5p_2}
@c
@end display
@end ifnottex


This function is not currently used anywhere, but it may turn out to be
useful for something. 
@end deftypefn

@deftypefn {@code{const} operator} Transform operator* ({const real} @var{r})
Multiplication of a @code{Transform} by a scalar without assignment.
The return value is a @code{Transform} 
@math{A}.
If @code{this.matrix} has elements 
@math{E_T}, then @code{A.matrix} has elements @math{E_A} such that 
@c
@iftex
@tex
$E_A = r \times E_T$ 
@end tex
@end iftex
@ifnottex
@math{E_A =} @TMS{r,E_T}
@end ifnottex
@c
for all @math{E}.
@c
@end deftypefn

  
@deftypefn Operator Transform operator*= ({const Transform&} @var{t})
Performs matrix multiplication on @code{matrix} and
@code{t.matrix}.  The result is assigned to @code{matrix}.
@var{t} is returned, @emph{not} @code{*this}!  This makes it possible to
chain invocations of this function:

@example
Transform a;
a.shift(1, 1, 1);
Transform b;
b.rotate(0, 90);
Transform c;
c.shear(5, 4);
Transform d;
d.scale(3, 4, 5);
@end example

Let @math{a_m}, @math{b_m}, and @math{c_m} stand for 
@code{a.matrix}, @code{b.matrix}, @code{c.matrix}, and @code{d.matrix}
respectively:
@c
@iftex
@tex
\bigskip
\line{\hss$a_m =\pmatrix{  1&       0&       0&       0\cr
                           0&       1&       0&       0\cr
                           0&       0&       1&       0\cr 
                           1&       1&       1&       1\cr}$\hfil 
          $b_m =\pmatrix{0.5&     0.5&   0.707&       0\cr  
                       0.146&   0.854&    -0.5&       0\cr  
                      -0.854&   0.146&     0.5&       0\cr  
                           0&       0&       0&       1\cr}$\hss}
\bigskip
\line{\hss$c_m =\pmatrix{1&      12&      14&       0\cr 
     10&       1&      15&       0\cr  
     11&      13&       1&       0\cr  
      0&       0&       0&       1\cr}$\hfil
             $d_m =\pmatrix{3&       0&       0&       0\cr  
                         0&       4&       0&       0\cr  
                         0&       0&       5&       0\cr  
                         0&       0&       0&       1\cr}$\hss}
\bigskip
@end tex
@end iftex
@ifnottex
@display 
@math{a_m =
1        0        0        0
0        1        0        0
0        0        1        0 
1        1        1        1}

@math{b_m = 
 0.5      0.5        0.707      0  
 0.146    0.854     -0.5        0  
-0.854    0.146      0.5        0  
 0        0          0          1}

@math{c_m = 
 1       12       14        0 
10        1       15        0  
11       13        1        0  
 0        0        0        1}

@math{d_m =
3        0        0        0  
0        4        0        0  
0        0        5        0  
0        0        0        1}
@c
@end display
@end ifnottex
@c
@code{a *= b *= c *= d;}@*
@code{a}, @code{b}, and @code{c} are transformed by @code{d}, which
remains unchanged.

@noindent
Now,
@iftex
@tex
\bigskip
\line {\hss$a_m =\pmatrix{3&       0&       0&       0\cr  
      0&       4&       0&       0\cr  
      0&       0&       5&       0\cr  
      3&       4&       5&       1\cr}$\hfil 
           $b_m =\pmatrix{1.5&       2&    3.54&       0\cr  
                       -0.439&    3.41&    -2.5&       0\cr  
                        -2.56&   0.586&     2.5&       0\cr  
                            0&       0&       0&       1\cr}$\hss}
\bigskip
\line{\hfil $c_m =\pmatrix{3&      48&      70&       0\cr  
     30&       4&      75&       0\cr  
     33&      52&       5&       0\cr  
      0&       0&       0&       1\cr}$\hfil}
\bigskip
@end tex
@end iftex
@ifnottex
@display 
@math{a_m =
3        0        0        0   
0        4        0        0   
0        0        5        0   
3        4        5        1}

@math{b_m =
 1.5     2       3.54  0   
-0.439   3.41   -2.5   0   
-2.56    0.586   2.5   0   
 0       0       0     1}

@math{c_m =
 3       48       70        0   
30        4       75        0   
33       52        5        0   
 0        0        0        1}
@end display
@end ifnottex
@c
@math{d_m} is unchanged.


@c
@end deftypefn

@deftypefn {@code{const} operator} Transform operator* ({const Transform} @var{t})
Multiplication of a @code{Transform} by another @code{Transform} without
assignment. 
The return value is a @code{Transform} whose @code{matrix} contains
values that are the result of the matrix multiplication of
@code{matrix} and @code{t.matrix}.
@end deftypefn


@node Matrix Inversion, Setting Values Transforms, Transform Operators, Transform Reference
@section Matrix Inversion

@deftypefn {@code{const} function} Transform inverse (void)
@deftypefnx {Function} Transform inverse ([bool @var{assign} = @code{false}])
Returns a @code{Transform} @code{T} with a @code{T.matrix} that is the
inverse of @code{matrix}.  If @var{assign}@equiv{}@code{true}, then
@code{matrix} is set to its inverse.

In the @code{const} version, @code{matrix} remains unchanged.
The second should only ever be called with @code{true} as its
@var{assign} argument.  If you're tempted call @code{inverse(false)},
you might as well just leave out the argument, which issues a warning
message, and calls the @code{const} version.
@end deftypefn

@node Setting Values Transforms, Querying Transforms, Matrix Inversion, Transform Reference
@section Setting Values

@deftypefun void set_element ({const unsigned short} @var{row}, {const unsigned short} @var{col}, real @var{r})
Sets the element of @code{matrix} indicated by the arguments to @var{r}.

@example
Transform t;
t.set_element(0, 2, -3.45569);
t.show("t:");
@print{} t:
      1       0   -3.46       0
      0       1       0       0
      0       0       1       0
      0       0       0       1
@end example
@end deftypefun   

@node Querying Transforms, Returning Information for Transforms, Setting Values Transforms, Transform Reference
@section Querying

@deftypefun bool is_identity (void)
Returns @code{true} if @code{*this} is the identity @code{Transform},
otherwise @code{false}.  This function has both a @code{const} and a
non-@code{const} version.  In the non-@code{const} version,
@code{clean()} is called on @code{*this} before comparing the elements of
@code{matrix} with 1 (for the main diagonal) and 0 (for the other
elements).  In the @code{const} version, @code{*this} is copied,
@code{clean()} is called on the copy, and the elements of the copy's
@code{matrix} are compared with 0 and 1.
@end deftypefun

@deftypefn {@code{const} function} real get_element ({const unsigned short} @var{row}, {const unsigned short} @var{col})
Returns the value stored in the element of @code{matrix} indicated by the arguments.

@example
Transform t;
t.shift(1, 2, 3);
t.scale(2.5, -1.2, 4);
t.rotate(30, 15, 60);
t.show("t:");
@print{} t: 
    1.21    2.09   0.647       0 
   0.822  -0.654    0.58       0 
   -2.18   0.224    3.35       0 
   -3.69    1.45    11.8       1 
cout << t.get_element(2, 1);
@print{} 0.224
@end example
@end deftypefn 
 
@node Returning Information for Transforms, Showing Transforms, Querying Transforms, Transform Reference
@section Returning Information

@deftypefn {Static function} real epsilon (void)
Returns the positive @code{real} value of smallest magnitude 
@math{\epsilon} which an element of a @code{Transform} should
contain.  An element of a @code{Transform} may also contain
@math{-\epsilon}. 

The value @math{\epsilon} is used for in the
function @code{clean()} (@pxref{Cleaning Transforms,,Transform
Reference; Cleaning}).  
It will also be used for comparing @code{Transforms}, when I've added
the equality operator @code{Transform::operator==()}.

@code{epsilon()} returns different values, depending on whether 
@code{real} is @code{float} or @code{double}:
If @code{real} is @code{float} (the default), @code{epsilon()} 
returns 0.00001.
If @code{real} is @code{double}, it returns 0.000000001.

@b{Please note}:  I haven't tested whether 0.000000001 is a good
value yet, so users should be aware of this if they set @code{real} to
@code{double}!@c
@c
@footnote{For that matter, I haven't really tested whether 0.00001 is a
good value when @code{real} is @code{float}.} 
@c
The way to test this is to transform two different
@code{Transforms} 
@math{t_1} and @math{t_2} 
using different rotations in such a way that the end
result should be the same for both @code{Transforms}.  
Let @math{\epsilon} stand for the value returned by @code{epsilon()}.
If for all sets of
corresponding elements @math{E_1} and @math{E_2} of @math{t_1} and
@math{t_2}, @math{||E_1| - |E_2|| \le \epsilon}, then 
@math{\epsilon} is a good value. 
@c !! TO DO: 
It will be easier to test this when I've added
@code{Transform::operator==()}. 

Rotation causes a significant loss of precision to due to the use of the
@code{sin()} and @code{cos()} functions.  Therefore, neither
@code{Transform::epsilon()} nor @code{Point::epsilon()} 
(@pxref{Returning Information for Points,,Point Reference; Returning
Information}) can be as small as I'd like them to be.  If they are two
small, operations that test for equality of @code{Transforms} and
@code{Points} will return @code{false} for objects that should be equal.
@end deftypefn

@node Showing Transforms, Affine Transformations for Transforms, Returning Information for Transforms, Transform Reference
@section Showing

@deftypefn {@code{const} function} void show ([string @var{text} = ""])
If the optional argument @var{text} is used, and is not the empty
@code{string} (@var{""}), @var{text} is printed on a line of its own to
the standard output first.  Otherwise, @code{"Transform:"} is printed
on a line of its own to the standard output. 
Then, the elements of @code{matrix} are printed to standard output.  

@example
Transform t;
t.show("t:");
@print{} t:
      1       0       0       0 
      0       1       0       0 
      0       0       1       0 
      0       0       0       1 
t.scale(1, 2, 3);
t.shift(1, 1, 1);
t.rotate(90, 90, 90);
t.show("t:");
@print{} t:
      0       0       1       0 
      0       2       0       0 
     -3       0       0       0 
     -1       1       1       1 
@end example


@end deftypefn

@node Affine Transformations for Transforms, Alignment with an Axis for Transforms, Showing Transforms, Transform Reference
@section Affine Transformations

The affine transformation functions use their arguments to create a new 
@code{Transform} @code{t} (local to the function) representing the
appropriate transformation. Then, @code{*this} is multiplied by @code{t}
and @code{t} is returned. 
Returning @code{t} instead of @code{*this} makes it possible to put the
affine transformation function at the end of a chain of invocations of
@code{Transform::operator*=()}:


@example
Transform t0, t1, t2, t3;
@dots{}
t0 *= t1 *= t2 *= t3.scale(2, 3.5, 9);
@end example

@code{t0}, @code{t1}, and @code{t2} are all multiplied by the
@code{Transform} with 
@c
@iftex
@tex 
$$@code{matrix}=\pmatrix{2&  0&0&0\cr
                         0&3.5&0&0\cr 
                         0&  0&9&0\cr 
                         0&  0&0&1\cr}$$
@end tex
@end iftex
@ifnottex
@display
@code{matrix} @math{=
2   0    0  0
0   3.5  0  0 
0   0    9  0 
0   0    0  1}
@end display
@end ifnottex
@c
representing the scaling operation, @emph{not} @code{t3}, which may
represent a combination of transformations.

@deftypefun Transform scale (real @var{x}, [real @var{y} = 1, [real @var{z} = 1]])
Creates a @code{Transform t} representing the scaling operation locally,
multiplies @code{*this} by @code{t}, and returns @code{t}.  
A @code{Transform} representing scaling only, when applied to a
@code{Point p}, will cause its x-coordinate to be multiplied by
@var{x}, its y-coordinate to be multiplied by @var{y}, and its
z-coordinate to be multiplied by @var{z}.

@example
@code{Transform t;} 
@code{t.scale(@var{x}, @var{y}, @var{z});}
@end example
@c
@iftex
@tex
%% KLUDGE!!  This gets the arrow lined up correctly, but only so long as
%% the format doesn't change!.  LDF 2003.07.06.
\hskip 28.90755pt
@result{} ${\tt t.matrix}=\pmatrix{x&0&0&0\cr
                           0&y&0&0\cr 
                           0&0&z&0\cr 
                           0&0&0&1\cr}$
\bigskip
@end tex
@end iftex
@ifnottex
@display 
@result{} @code{t.matrix} @math{=
x 0 0 0
0 y 0 0 
0 0 z 0 
0 0 0 1}
@c
@end display
@end ifnottex
@c

@c

@example
Transform t;
t.scale(12.5, 20, 1.3);
t.show("t:");
@print{} t:
   12.5       0       0       0 
      0      20       0       0 
      0       0     1.3       0 
      0       0       0       1 
@end example
@end deftypefun

@deftypefun Transform shear (real @var{xy}, [real @var{xz} = 0, [real @var{yx} = 0, [real @var{yz} = 0, [real @var{zx} = 0, [real @var{zy} = 0]]]]])
Creates a @code{Transform t} representing the shearing operation locally,
multiplies @code{*this} by @code{t}, and returns @code{t}.  

When applied to a @code{Point}, shearing causes each coordinate to be
modified according to the values of the other coordinates and the
arguments to @code{shear}:


@example
Point p(x,y,z);
Transform t;
t.shear(a, b, c, d, e, f);
p *= t;
@end example
@display 
@c
@iftex
@tex 
\vskip-2\baselineskip
@end tex
@end iftex
@c
@result{} @math{p = ((x + ay + bz), (y + cx + dz), (z + ex + fy))}
@c
@iftex 
@tex 
\bigskip
@end tex
@end iftex
@c
@end display

@example
Transform t;
t.shear(2, 3, 4, 5, 6, 7);
t.show("t:");
@print{} t:
      1       4       6       0 
      2       1       7       0 
      3       5       1       0 
      0       0       0       1 
@end example

@end deftypefun

@deftypefun Transform shift (real @var{x}, [real @var{y} = 0, [real @var{z} = 0]])
@deftypefunx Transform shift ({const Point&} @var{p})

These functions create a @code{Transform t} representing the shifting
operation locally, multiplies @code{*this} by @code{t}, and returns @code{t}.  

The version with the argument @code{const Point&} @var{p} 
passes the updated x, y, and z-coordinates of @var{p} (from
@code{world_coordinates}) to the
version with three @code{real} arguments.

When a @code{Transform} representing a single shifting operation only
is applied to a @code{Point}, the @var{x}, 
@var{y}, and @var{z} arguments are added to the corresponding
coordinates of the @code{Point}: 

@example
Point p(x,y,z);
Transform t;
t.shift(a, b, c);
p *= t;
@end example
@display 
@c
@iftex
@tex 
\vskip-2\baselineskip
@end tex
@end iftex
@c
@result{} @math{p = (x + a, y + b, z + c)}
@c
@end display
@c
@end deftypefun


@deftypefun Transform shift_times (real @var{x}, [real @var{y} = 1, [real @var{z} = 1]])
Multiplies the corresponding elements of @code{matrix} by 
the @code{real} arguments, i.e., 
@code{matrix[3][0]} is multiplied by @var{x}, 
@code{matrix[3][1]} is multiplied by @var{y}, and 
@code{matrix[3][2]} is multiplied by @var{z}.  Returns @code{*this}. 

Ordinary shifting is additive, so a special function is needed to
multiply the elements of @code{matrix} responsible for shifting.
The effect of @code{shift_times()} is to modify a @code{Transform}
representing a shifting operation such that the direction of the shift
is maintained, while changing the distance.

If the @code{Transform} represents other operations in addition to
shifting, e.g., scaling and/or shearing, the effect of 
@code{shift_times()} may be unpredictable.@c
@c
@footnote{For a person, not in the sense of the program behaving
unpredictably.}  

@example
Transform t;
t.shift(1, 2, 3);
@end example
@c
@iftex
@tex
\smallskip
%% KLUDGE!!  This gets the arrow lined up correctly, but only so long as
%% the format doesn't change!.  LDF 2003.07.06.
\hskip 28.90755pt
@result{} ${\tt t.matrix}=@pmatrix{1&0&0&0@cr
           0&1&0&0@cr
           0&0&1&0@cr
           1&2&3&1@cr}$
\bigskip
@end tex
@end iftex
@c
@ifnottex
@display 
@result{} @code{t.matrix} @math{=
1 0 0 0
0 1 0 0
0 0 1 0
1 2 3 1}
@end display
@end ifnottex
@c

@example
t.shift_times(2, 2, 2);
@end example
@c
@iftex
@tex
\smallskip
%% KLUDGE!!  This gets the arrow lined up correctly, but only so long as
%% the format doesn't change!.  LDF 2003.07.06.
\hskip 28.90755pt
@result{} ${\tt t.matrix}=@pmatrix{1&0&0&0@cr
           0&1&0&0@cr
           0&0&1&0@cr
           2&4&6&1@cr}$
\bigskip
@end tex
@end iftex
@c
@ifnottex
@display
@result{} @code{t.matrix} @math{=
1 0 0 0
0 1 0 0
0 0 1 0
2 4 6 1}
@end display
@end ifnottex
@c

@example
Rectangle r[4];
r[0].set(origin, 1, 1, 90);
r[3] = r[2] = r[1] = r[0];
Transform t;  
t.shift(1.5, 1.5);
r[0] *= t;
r[0].draw();
t.shift_times(1.5, 1.5);
r[1] *= t;
r[1].draw();
t.shift_times(1.5, 1.5);
r[2] *= t;
r[2].draw();
t.shift_times(1.5, 1.5);
r[3] *= t;
r[3].draw();
@end example

@c
@iftex
@tex
\ifmakeexamples
\BEX
\BGRP
\immediate\write\examples{Rectangle r[4];} 
\immediate\write\examples{r[0].set(origin, 1, 1, 90);}
\immediate\write\examples{r[3] = r[2] = r[1] = r[0];} 
\immediate\write\examples{Transform t;}  
\immediate\write\examples{t.reset();}
\immediate\write\examples{t.shift(1.5, 1.5);} 
\immediate\write\examples{r[0] *= t;} 
\immediate\write\examples{r[0].draw();} 
\immediate\write\examples{r[0].get_center().label("$r_0$", "");}
%  
\immediate\write\examples{t.shift_times(1.5, 1.5);} 
\immediate\write\examples{r[1] *= t;} 
\immediate\write\examples{r[1].get_center().label("$r_1$", "");}
\immediate\write\examples{r[1].draw();}
%
\immediate\write\examples{t.shift_times(1.5, 1.5);} 
\immediate\write\examples{r[2] *= t;}
\immediate\write\examples{r[2].get_center().label("$r_2$", "");}
\immediate\write\examples{r[2].draw();}
%
\immediate\write\examples{t.shift_times(1.5, 1.5);}
\immediate\write\examples{r[3] *= t;}
\immediate\write\examples{r[3].get_center().label("$r_3$", "");}
\immediate\write\examples{r[3].draw();}
\OEX{Projections::PARALLEL_X_Y}
\EGRP
\EEX 1
\fi
\PEX
@end tex
@end iftex

@ifhtml
@html
<p align="center">
<br>
<img src="./graphics/png/3DLDFmp.73.png"
alt="[Figure 73. Not displayed.]"
/>
<br>
<br>
Fig. 73.
<br>
</p>
@end html
@end ifhtml

@ifinfo
[Figure 73 not displayed.]
@end ifinfo

@c

@example
Cuboid c(origin, 1, 1, 1);
c.draw();
Transform t;
t.rotate(30, 30, 30);
t.shift(1, 0, 1);
c *= t;
c.draw();
t.shift_times(1.5, 0, 1.5);
c *= t;            
c.draw();          
t.shift_times(1.5, 0, 1.5);
c *= t;            
c.draw();          
t.shift_times(1.5, 0, 1.5);
c *= t;            
c.draw();          
t.shift_times(1.5, 0, 1.5);
c *= t;
c.draw();
@end example

@c
@iftex
@tex
\ifmakeexamples
\BEX
\BGRP
\immediate\write\examples{default_focus.set(2, 3, -10, 2, 3, 10, 10);}
\immediate\write\examples{Cuboid c(origin, 1, 1, 1);}
\immediate\write\examples{c.draw();}
\immediate\write\examples{Transform t;}
\immediate\write\examples{t.rotate(30, 30, 30);}
\immediate\write\examples{t.shift(1, 0, 1);}
\immediate\write\examples{c *= t;}
\immediate\write\examples{c.draw();}
\immediate\write\examples{t.shift_times(1.5, 0, 1.5);}
\immediate\write\examples{c *= t;            }
\immediate\write\examples{c.draw();          }
\immediate\write\examples{t.shift_times(1.5, 0, 1.5);}
\immediate\write\examples{c *= t;            }
\immediate\write\examples{c.draw();          }
\immediate\write\examples{t.shift_times(1.5, 0, 1.5);}
\immediate\write\examples{c *= t;            }
\immediate\write\examples{c.draw();          }
\immediate\write\examples{t.shift_times(1.5, 0, 1.5);}
\immediate\write\examples{c *= t;}
\immediate\write\examples{c.draw();}
\OEX{}
\EGRP
\EEX 1
\fi
\PEX
@end tex
@end iftex

@ifhtml
@html
<p align="center">
<br>
<img src="./graphics/png/3DLDFmp.74.png"
alt="[Figure 74. Not displayed.]"
/>
<br>
<br>
Fig. 74.
<br>
</p>
@end html
@end ifhtml

@ifinfo
[Figure 74 not displayed.]
@end ifinfo

@c
@end deftypefun

@deftypefun Transform rotate (real @var{x}, [real @var{y} = 0, [real @var{z} = 0]])
Rotation around the main axes.
Creates a @code{Transform t} representing the rotation,
multiplies @code{*this} by @code{t}, and returns @code{t}.  
@end deftypefun 

@deftypefun Transform rotate (Point @var{p0}, Point @var{p1}, [{const real} @var{angle} = 180])
Rotation around an arbitrary axis.  The @code{Point} arguments represent
the end points of the axis, and @var{angle} is the angle of rotation.  
Since @DEG{180} rotation is needed so often, 180 is the default for
@var{angle}.
@end deftypefun 

@deftypefun Transform rotate ({const Path&} @var{p},  [{const real} @var{angle} = 180])
Rotation around an arbitrary axis.  @code{Path} argument.  
The @code{Path} @var{p} must be linear, i.e., @code{p.is_linear()} must
return @code{true}.  @xref{Querying Paths,,Path Reference; Querying}.
@end deftypefun 

@node Alignment with an Axis for Transforms, Resetting Transforms, Affine Transformations for Transforms, Transform Reference
@section Alignment with an Axis

@deftypefun Transform align_with_axis (Point @var{p0}, Point @var{p1}, [char @var{axis} = 'z'])
Returns the @code{Transform} that would align the line through @var{p0}
and @var{p1} with the major axis denoted by the @var{axis} argument.
The default is the z-axis.  This function is used in the functions that
find intersections. 

@example
Point P0(1, 1, 1);
Point P1(2, 3, 4);
P0.draw(P1);
P0.dotlabel("$P_0$"); 
P1.dotlabel("$P_1$"); 
Transform t;
t.align_with_axis(P0, P1, 'z');
P0 *= P1 *= t;
t.show("t:");
@print{} t:
     0.949  -0.169   0.267       0 
         0   0.845   0.535       0 
    -0.316  -0.507   0.802       0 
    -0.632  -0.169    -1.6       1 
P0.show("P0:");
@print{} P0: (0, 0, 0)
P1.show("P1:");
@print{} P1: (0, 0, 3.74)
@end example

The following example shows how @code{align_with_axis()} can be used for
putting plane figures into a 
major plane.  

@example
default_focus.set(2, 3, -10, 2, 3, 10, 10);
Circle c(origin, 3, 75, 25, 6);
c.shift(2, 3);
c.draw();
Point n = c.get_normal();
n.shift(c.get_center());
Transform t;
t.align_with_axis(c.get_center(), n, 'y');
t.show("t:");
@print{} t:
  0.686   0.379  -0.621       0 
  0.543     0.3   0.784       0 
  0.483  -0.875       0       0 
     -3   -1.66   -1.11       1 
n *= c *= t;
c.draw();
c.show("c:");
@print{} c:
fill_draw_value == 0
(1.31, 0, -0.728) .. (1.49, 0, -0.171) .. 
(1.44, 0, 0.413) .. (1.17, 0, 0.933) .. 
(0.728, 0, 1.31) .. (0.171, 0, 1.49) .. 
(-0.413, 0, 1.44) .. (-0.933, 0, 1.17) .. 
(-1.31, 0, 0.728) .. (-1.49, 0, 0.171) .. 
(-1.44, 0, -0.413) .. (-1.17, 0, -0.933) .. 
(-0.728, 0, -1.31) .. (-0.171, 0, -1.49) .. 
(0.413, 0, -1.44) .. (0.933, 0, -1.17) .. cycle;
n.show("n:");
@print{} n: (0, 1, 0)
@end example

@c
@iftex
@tex
\ifmakeexamples
\BEX
\BGRP
\immediate\write\examples{default_focus.set(2, 3, -10, 2, 3, 10, 10);}
\immediate\write\examples{Circle c(origin, 3, 75, 25, 6);}
\immediate\write\examples{c.shift(2, 3);}
\immediate\write\examples{c.draw();}
\immediate\write\examples{c.get_center().label("$c$", "llft");}
\immediate\write\examples{Point n = c.get_normal();}
\immediate\write\examples{n.shift(c.get_center());}
\immediate\write\examples{n.label("$\DBKS{vec}\OCB n\CCB$", "urt"); }
\immediate\write\examples{c.get_center().drawarrow(n);}
\immediate\write\examples{Transform t;}
\immediate\write\examples{t.align_with_axis(c.get_center(), n, 'y');}
\immediate\write\examples{n *= c *= t;}
\immediate\write\examples{c.draw();}
\immediate\write\examples{c.get_center().label("$c$", "lrt");}
\immediate\write\examples{n.label("$\DBKS{vec}\OCB n\CCB$", "rt");}
\immediate\write\examples{draw_axes(gray, 0, "d", "d", "rt");}
\immediate\write\examples{c.get_center().drawarrow(n);}
\OEX{}
\EGRP
\EEX 1
\fi
\PEX  
@end tex
@end iftex

@ifhtml
@html
<p align="center">
<br>
<img src="./graphics/png/3DLDFmp.75.png"
alt="[Figure 75. Not displayed.]"
/>
<br>
<br>
Fig. 75.
<br>
</p>
@end html
@end ifhtml

@ifinfo
[Figure 75 not displayed.]
@end ifinfo

@c


@end deftypefun 

@node Resetting Transforms, Cleaning Transforms, Alignment with an Axis for Transforms, Transform Reference
@section Resetting

@deftypefun void reset (void)
Resets @var{matrix} to the identity matrix.
@end deftypefun

@node Cleaning Transforms,  , Resetting Transforms, Transform Reference
@section Cleaning

@deftypefun void clean (void)
Sets elements in @var{matrix} whose absolute values are 
@math{<} @code{epsilon()} to 0.
@end deftypefun


