You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

251 lines
9.7 KiB

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