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