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