Home | History | Annotate | Download | only in doc
      1 namespace Eigen {
      2 
      3 /** \page TutorialGeometry Tutorial page 8 - Geometry
      4     \ingroup Tutorial
      5 
      6 \li \b Previous: \ref TutorialReductionsVisitorsBroadcasting
      7 \li \b Next: \ref TutorialSparse
      8 
      9 In this tutorial, we will briefly introduce the many possibilities offered by the \ref Geometry_Module "geometry module", namely 2D and 3D rotations and projective or affine transformations.
     10 
     11 \b Table \b of \b contents
     12   - \ref TutorialGeoElementaryTransformations
     13   - \ref TutorialGeoCommontransformationAPI
     14   - \ref TutorialGeoTransform
     15   - \ref TutorialGeoEulerAngles
     16 
     17 Eigen's Geometry module provides two different kinds of geometric transformations:
     18   - Abstract transformations, such as rotations (represented by \ref AngleAxis "angle and axis" or by a \ref Quaternion "quaternion"), \ref Translation "translations", \ref Scaling "scalings". These transformations are NOT represented as matrices, but you can nevertheless mix them with matrices and vectors in expressions, and convert them to matrices if you wish.
     19   - Projective or affine transformation matrices: see the Transform class. These are really matrices.
     20 
     21 \note If you are working with OpenGL 4x4 matrices then Affine3f and Affine3d are what you want. Since Eigen defaults to column-major storage, you can directly use the Transform::data() method to pass your transformation matrix to OpenGL.
     22 
     23 You can construct a Transform from an abstract transformation, like this:
     24 \code
     25   Transform t(AngleAxis(angle,axis));
     26 \endcode
     27 or like this:
     28 \code
     29   Transform t;
     30   t = AngleAxis(angle,axis);
     31 \endcode
     32 But note that unfortunately, because of how C++ works, you can \b not do this:
     33 \code
     34   Transform t = AngleAxis(angle,axis);
     35 \endcode
     36 <span class="note">\b Explanation: In the C++ language, this would require Transform to have a non-explicit conversion constructor from AngleAxis, but we really don't want to allow implicit casting here.
     37 </span>
     38 
     39 \section TutorialGeoElementaryTransformations Transformation types
     40 
     41 <table class="manual">
     42 <tr><th>Transformation type</th><th>Typical initialization code</th></tr>
     43 <tr><td>
     44 \ref Rotation2D "2D rotation" from an angle</td><td>\code
     45 Rotation2D<float> rot2(angle_in_radian);\endcode</td></tr>
     46 <tr class="alt"><td>
     47 3D rotation as an \ref AngleAxis "angle + axis"</td><td>\code
     48 AngleAxis<float> aa(angle_in_radian, Vector3f(ax,ay,az));\endcode
     49 <span class="note">The axis vector must be normalized.</span></td></tr>
     50 <tr><td>
     51 3D rotation as a \ref Quaternion "quaternion"</td><td>\code
     52 Quaternion<float> q;  q = AngleAxis<float>(angle_in_radian, axis);\endcode</td></tr>
     53 <tr class="alt"><td>
     54 N-D Scaling</td><td>\code
     55 Scaling(sx, sy)
     56 Scaling(sx, sy, sz)
     57 Scaling(s)
     58 Scaling(vecN)\endcode</td></tr>
     59 <tr><td>
     60 N-D Translation</td><td>\code
     61 Translation<float,2>(tx, ty)
     62 Translation<float,3>(tx, ty, tz)
     63 Translation<float,N>(s)
     64 Translation<float,N>(vecN)\endcode</td></tr>
     65 <tr class="alt"><td>
     66 N-D \ref TutorialGeoTransform "Affine transformation"</td><td>\code
     67 Transform<float,N,Affine> t = concatenation_of_any_transformations;
     68 Transform<float,3,Affine> t = Translation3f(p) * AngleAxisf(a,axis) * Scaling(s);\endcode</td></tr>
     69 <tr><td>
     70 N-D Linear transformations \n
     71 <em class=note>(pure rotations, \n scaling, etc.)</em></td><td>\code
     72 Matrix<float,N> t = concatenation_of_rotations_and_scalings;
     73 Matrix<float,2> t = Rotation2Df(a) * Scaling(s);
     74 Matrix<float,3> t = AngleAxisf(a,axis) * Scaling(s);\endcode</td></tr>
     75 </table>
     76 
     77 <strong>Notes on rotations</strong>\n To transform more than a single vector the preferred
     78 representations are rotation matrices, while for other usages Quaternion is the
     79 representation of choice as they are compact, fast and stable. Finally Rotation2D and
     80 AngleAxis are mainly convenient types to create other rotation objects.
     81 
     82 <strong>Notes on Translation and Scaling</strong>\n Like AngleAxis, these classes were
     83 designed to simplify the creation/initialization of linear (Matrix) and affine (Transform)
     84 transformations. Nevertheless, unlike AngleAxis which is inefficient to use, these classes
     85 might still be interesting to write generic and efficient algorithms taking as input any
     86 kind of transformations.
     87 
     88 Any of the above transformation types can be converted to any other types of the same nature,
     89 or to a more generic type. Here are some additional examples:
     90 <table class="manual">
     91 <tr><td>\code
     92 Rotation2Df r;  r  = Matrix2f(..);       // assumes a pure rotation matrix
     93 AngleAxisf aa;  aa = Quaternionf(..);
     94 AngleAxisf aa;  aa = Matrix3f(..);       // assumes a pure rotation matrix
     95 Matrix2f m;     m  = Rotation2Df(..);
     96 Matrix3f m;     m  = Quaternionf(..);       Matrix3f m;   m = Scaling(..);
     97 Affine3f m;     m  = AngleAxis3f(..);       Affine3f m;   m = Scaling(..);
     98 Affine3f m;     m  = Translation3f(..);     Affine3f m;   m = Matrix3f(..);
     99 \endcode</td></tr>
    100 </table>
    101 
    102 
    103 <a href="#" class="top">top</a>\section TutorialGeoCommontransformationAPI Common API across transformation types
    104 
    105 To some extent, Eigen's \ref Geometry_Module "geometry module" allows you to write
    106 generic algorithms working on any kind of transformation representations:
    107 <table class="manual">
    108 <tr><td>
    109 Concatenation of two transformations</td><td>\code
    110 gen1 * gen2;\endcode</td></tr>
    111 <tr class="alt"><td>Apply the transformation to a vector</td><td>\code
    112 vec2 = gen1 * vec1;\endcode</td></tr>
    113 <tr><td>Get the inverse of the transformation</td><td>\code
    114 gen2 = gen1.inverse();\endcode</td></tr>
    115 <tr class="alt"><td>Spherical interpolation \n (Rotation2D and Quaternion only)</td><td>\code
    116 rot3 = rot1.slerp(alpha,rot2);\endcode</td></tr>
    117 </table>
    118 
    119 
    120 
    121 <a href="#" class="top">top</a>\section TutorialGeoTransform Affine transformations
    122 Generic affine transformations are represented by the Transform class which internaly
    123 is a (Dim+1)^2 matrix. In Eigen we have chosen to not distinghish between points and
    124 vectors such that all points are actually represented by displacement vectors from the
    125 origin ( \f$ \mathbf{p} \equiv \mathbf{p}-0 \f$ ). With that in mind, real points and
    126 vector distinguish when the transformation is applied.
    127 <table class="manual">
    128 <tr><td>
    129 Apply the transformation to a \b point </td><td>\code
    130 VectorNf p1, p2;
    131 p2 = t * p1;\endcode</td></tr>
    132 <tr class="alt"><td>
    133 Apply the transformation to a \b vector </td><td>\code
    134 VectorNf vec1, vec2;
    135 vec2 = t.linear() * vec1;\endcode</td></tr>
    136 <tr><td>
    137 Apply a \em general transformation \n to a \b normal \b vector
    138 (<a href="http://www.cgafaq.info/wiki/Transforming_normals">explanations</a>)</td><td>\code
    139 VectorNf n1, n2;
    140 MatrixNf normalMatrix = t.linear().inverse().transpose();
    141 n2 = (normalMatrix * n1).normalized();\endcode</td></tr>
    142 <tr class="alt"><td>
    143 Apply a transformation with \em pure \em rotation \n to a \b normal \b vector
    144 (no scaling, no shear)</td><td>\code
    145 n2 = t.linear() * n1;\endcode</td></tr>
    146 <tr><td>
    147 OpenGL compatibility \b 3D </td><td>\code
    148 glLoadMatrixf(t.data());\endcode</td></tr>
    149 <tr class="alt"><td>
    150 OpenGL compatibility \b 2D </td><td>\code
    151 Affine3f aux(Affine3f::Identity());
    152 aux.linear().topLeftCorner<2,2>() = t.linear();
    153 aux.translation().start<2>() = t.translation();
    154 glLoadMatrixf(aux.data());\endcode</td></tr>
    155 </table>
    156 
    157 \b Component \b accessors
    158 <table class="manual">
    159 <tr><td>
    160 full read-write access to the internal matrix</td><td>\code
    161 t.matrix() = matN1xN1;    // N1 means N+1
    162 matN1xN1 = t.matrix();
    163 \endcode</td></tr>
    164 <tr class="alt"><td>
    165 coefficient accessors</td><td>\code
    166 t(i,j) = scalar;   <=>   t.matrix()(i,j) = scalar;
    167 scalar = t(i,j);   <=>   scalar = t.matrix()(i,j);
    168 \endcode</td></tr>
    169 <tr><td>
    170 translation part</td><td>\code
    171 t.translation() = vecN;
    172 vecN = t.translation();
    173 \endcode</td></tr>
    174 <tr class="alt"><td>
    175 linear part</td><td>\code
    176 t.linear() = matNxN;
    177 matNxN = t.linear();
    178 \endcode</td></tr>
    179 <tr><td>
    180 extract the rotation matrix</td><td>\code
    181 matNxN = t.extractRotation();
    182 \endcode</td></tr>
    183 </table>
    184 
    185 
    186 \b Transformation \b creation \n
    187 While transformation objects can be created and updated concatenating elementary transformations,
    188 the Transform class also features a procedural API:
    189 <table class="manual">
    190 <tr><th></th><th>procedural API</th><th>equivalent natural API </th></tr>
    191 <tr><td>Translation</td><td>\code
    192 t.translate(Vector_(tx,ty,..));
    193 t.pretranslate(Vector_(tx,ty,..));
    194 \endcode</td><td>\code
    195 t *= Translation_(tx,ty,..);
    196 t = Translation_(tx,ty,..) * t;
    197 \endcode</td></tr>
    198 <tr class="alt"><td>\b Rotation \n <em class="note">In 2D and for the procedural API, any_rotation can also \n be an angle in radian</em></td><td>\code
    199 t.rotate(any_rotation);
    200 t.prerotate(any_rotation);
    201 \endcode</td><td>\code
    202 t *= any_rotation;
    203 t = any_rotation * t;
    204 \endcode</td></tr>
    205 <tr><td>Scaling</td><td>\code
    206 t.scale(Vector_(sx,sy,..));
    207 t.scale(s);
    208 t.prescale(Vector_(sx,sy,..));
    209 t.prescale(s);
    210 \endcode</td><td>\code
    211 t *= Scaling(sx,sy,..);
    212 t *= Scaling(s);
    213 t = Scaling(sx,sy,..) * t;
    214 t = Scaling(s) * t;
    215 \endcode</td></tr>
    216 <tr class="alt"><td>Shear transformation \n ( \b 2D \b only ! )</td><td>\code
    217 t.shear(sx,sy);
    218 t.preshear(sx,sy);
    219 \endcode</td><td></td></tr>
    220 </table>
    221 
    222 Note that in both API, any many transformations can be concatenated in a single expression as shown in the two following equivalent examples:
    223 <table class="manual">
    224 <tr><td>\code
    225 t.pretranslate(..).rotate(..).translate(..).scale(..);
    226 \endcode</td></tr>
    227 <tr><td>\code
    228 t = Translation_(..) * t * RotationType(..) * Translation_(..) * Scaling(..);
    229 \endcode</td></tr>
    230 </table>
    231 
    232 
    233 
    234 <a href="#" class="top">top</a>\section TutorialGeoEulerAngles Euler angles
    235 <table class="manual">
    236 <tr><td style="max-width:30em;">
    237 Euler angles might be convenient to create rotation objects.
    238 On the other hand, since there exist 24 different conventions, they are pretty confusing to use. This example shows how
    239 to create a rotation matrix according to the 2-1-2 convention.</td><td>\code
    240 Matrix3f m;
    241 m = AngleAxisf(angle1, Vector3f::UnitZ())
    242 *  * AngleAxisf(angle2, Vector3f::UnitY())
    243 *  * AngleAxisf(angle3, Vector3f::UnitZ());
    244 \endcode</td></tr>
    245 </table>
    246 
    247 \li \b Next: \ref TutorialSparse
    248 
    249 */
    250 
    251 }
    252