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