blob: eec21ac05062a57f8ade39a89491d7d5c9624670 [file] [log] [blame]
Gael Guennebaud99462972008-08-31 17:30:09 +00001namespace Eigen {
2
Gael Guennebaud41ea92d2010-07-04 10:14:47 +02003/** \page TutorialGeometry Tutorial page 8 - Geometry
Gael Guennebaud99462972008-08-31 17:30:09 +00004 \ingroup Tutorial
5
Jitse Niesen26cfe5a2010-07-09 11:59:29 +01006\li \b Previous: \ref TutorialReductionsVisitorsBroadcasting
Gael Guennebaud41ea92d2010-07-04 10:14:47 +02007\li \b Next: \ref TutorialSparse
Gael Guennebaud99462972008-08-31 17:30:09 +00008
Tim Holy16a2d892011-06-20 22:47:58 -05009In 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.
Gael Guennebaud99462972008-08-31 17:30:09 +000010
Gael Guennebaud2ea1e492012-12-28 18:58:07 +010011\tableofcontents
Gael Guennebaud99462972008-08-31 17:30:09 +000012
Benoit Jacob789ea9d2008-12-22 20:50:47 +000013Eigen's Geometry module provides two different kinds of geometric transformations:
14 - 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.
Gael Guennebaud41ea92d2010-07-04 10:14:47 +020015 - Projective or affine transformation matrices: see the Transform class. These are really matrices.
Benoit Jacob789ea9d2008-12-22 20:50:47 +000016
Hauke Heibel85fdcdf2010-08-17 20:03:50 +020017\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.
Benoit Jacob789ea9d2008-12-22 20:50:47 +000018
19You can construct a Transform from an abstract transformation, like this:
20\code
21 Transform t(AngleAxis(angle,axis));
22\endcode
23or like this:
24\code
25 Transform t;
26 t = AngleAxis(angle,axis);
27\endcode
28But note that unfortunately, because of how C++ works, you can \b not do this:
29\code
30 Transform t = AngleAxis(angle,axis);
31\endcode
32<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.
33</span>
34
Gael Guennebaud99462972008-08-31 17:30:09 +000035\section TutorialGeoElementaryTransformations Transformation types
36
Gael Guennebaudf66fe262010-10-19 11:40:49 +020037<table class="manual">
38<tr><th>Transformation type</th><th>Typical initialization code</th></tr>
Gael Guennebaud99462972008-08-31 17:30:09 +000039<tr><td>
Gael Guennebaud6825c8d2008-09-01 06:33:19 +000040\ref Rotation2D "2D rotation" from an angle</td><td>\code
Gael Guennebaud99462972008-08-31 17:30:09 +000041Rotation2D<float> rot2(angle_in_radian);\endcode</td></tr>
Gael Guennebaudf66fe262010-10-19 11:40:49 +020042<tr class="alt"><td>
Gael Guennebaud6825c8d2008-09-01 06:33:19 +0000433D rotation as an \ref AngleAxis "angle + axis"</td><td>\code
Gael Guennebaud57207232011-11-01 09:40:51 +010044AngleAxis<float> aa(angle_in_radian, Vector3f(ax,ay,az));\endcode
45<span class="note">The axis vector must be normalized.</span></td></tr>
Gael Guennebaud99462972008-08-31 17:30:09 +000046<tr><td>
Gael Guennebaud6825c8d2008-09-01 06:33:19 +0000473D rotation as a \ref Quaternion "quaternion"</td><td>\code
Gael Guennebaud5b71d442011-05-28 22:12:15 +020048Quaternion<float> q; q = AngleAxis<float>(angle_in_radian, axis);\endcode</td></tr>
Gael Guennebaudf66fe262010-10-19 11:40:49 +020049<tr class="alt"><td>
Gael Guennebaud99462972008-08-31 17:30:09 +000050N-D Scaling</td><td>\code
Gael Guennebaud17273732012-06-18 22:07:13 +020051Scaling(sx, sy)
52Scaling(sx, sy, sz)
53Scaling(s)
54Scaling(vecN)\endcode</td></tr>
Gael Guennebaud99462972008-08-31 17:30:09 +000055<tr><td>
56N-D Translation</td><td>\code
57Translation<float,2>(tx, ty)
58Translation<float,3>(tx, ty, tz)
59Translation<float,N>(s)
60Translation<float,N>(vecN)\endcode</td></tr>
Gael Guennebaudf66fe262010-10-19 11:40:49 +020061<tr class="alt"><td>
Gael Guennebaud99462972008-08-31 17:30:09 +000062N-D \ref TutorialGeoTransform "Affine transformation"</td><td>\code
Gael Guennebaudb5f32832010-10-06 13:27:14 +020063Transform<float,N,Affine> t = concatenation_of_any_transformations;
Gael Guennebaud17273732012-06-18 22:07:13 +020064Transform<float,3,Affine> t = Translation3f(p) * AngleAxisf(a,axis) * Scaling(s);\endcode</td></tr>
Gael Guennebaud99462972008-08-31 17:30:09 +000065<tr><td>
66N-D Linear transformations \n
67<em class=note>(pure rotations, \n scaling, etc.)</em></td><td>\code
68Matrix<float,N> t = concatenation_of_rotations_and_scalings;
Gael Guennebaud17273732012-06-18 22:07:13 +020069Matrix<float,2> t = Rotation2Df(a) * Scaling(s);
70Matrix<float,3> t = AngleAxisf(a,axis) * Scaling(s);\endcode</td></tr>
Gael Guennebaud99462972008-08-31 17:30:09 +000071</table>
72
73<strong>Notes on rotations</strong>\n To transform more than a single vector the preferred
74representations are rotation matrices, while for other usages Quaternion is the
75representation of choice as they are compact, fast and stable. Finally Rotation2D and
76AngleAxis are mainly convenient types to create other rotation objects.
77
Tim Holy16a2d892011-06-20 22:47:58 -050078<strong>Notes on Translation and Scaling</strong>\n Like AngleAxis, these classes were
Gael Guennebaud99462972008-08-31 17:30:09 +000079designed to simplify the creation/initialization of linear (Matrix) and affine (Transform)
80transformations. Nevertheless, unlike AngleAxis which is inefficient to use, these classes
81might still be interesting to write generic and efficient algorithms taking as input any
82kind of transformations.
83
84Any of the above transformation types can be converted to any other types of the same nature,
Gael Guennebaud582c1f92008-11-22 19:51:05 +000085or to a more generic type. Here are some additional examples:
Gael Guennebaudf66fe262010-10-19 11:40:49 +020086<table class="manual">
Gael Guennebaud99462972008-08-31 17:30:09 +000087<tr><td>\code
Gael Guennebaud5b71d442011-05-28 22:12:15 +020088Rotation2Df r; r = Matrix2f(..); // assumes a pure rotation matrix
89AngleAxisf aa; aa = Quaternionf(..);
90AngleAxisf aa; aa = Matrix3f(..); // assumes a pure rotation matrix
91Matrix2f m; m = Rotation2Df(..);
Gael Guennebaud17273732012-06-18 22:07:13 +020092Matrix3f m; m = Quaternionf(..); Matrix3f m; m = Scaling(..);
93Affine3f m; m = AngleAxis3f(..); Affine3f m; m = Scaling(..);
Gael Guennebaud5b71d442011-05-28 22:12:15 +020094Affine3f m; m = Translation3f(..); Affine3f m; m = Matrix3f(..);
Gael Guennebaud99462972008-08-31 17:30:09 +000095\endcode</td></tr>
96</table>
97
98
99<a href="#" class="top">top</a>\section TutorialGeoCommontransformationAPI Common API across transformation types
100
Gael Guennebauda4487ef2009-02-05 21:19:40 +0000101To some extent, Eigen's \ref Geometry_Module "geometry module" allows you to write
Gael Guennebaud99462972008-08-31 17:30:09 +0000102generic algorithms working on any kind of transformation representations:
Gael Guennebaudf66fe262010-10-19 11:40:49 +0200103<table class="manual">
Gael Guennebaud99462972008-08-31 17:30:09 +0000104<tr><td>
105Concatenation of two transformations</td><td>\code
106gen1 * gen2;\endcode</td></tr>
Gael Guennebaudf66fe262010-10-19 11:40:49 +0200107<tr class="alt"><td>Apply the transformation to a vector</td><td>\code
Gael Guennebaud99462972008-08-31 17:30:09 +0000108vec2 = gen1 * vec1;\endcode</td></tr>
109<tr><td>Get the inverse of the transformation</td><td>\code
110gen2 = gen1.inverse();\endcode</td></tr>
Gael Guennebaudf66fe262010-10-19 11:40:49 +0200111<tr class="alt"><td>Spherical interpolation \n (Rotation2D and Quaternion only)</td><td>\code
Gael Guennebaud99462972008-08-31 17:30:09 +0000112rot3 = rot1.slerp(alpha,rot2);\endcode</td></tr>
113</table>
114
115
116
117<a href="#" class="top">top</a>\section TutorialGeoTransform Affine transformations
118Generic affine transformations are represented by the Transform class which internaly
119is a (Dim+1)^2 matrix. In Eigen we have chosen to not distinghish between points and
120vectors such that all points are actually represented by displacement vectors from the
121origin ( \f$ \mathbf{p} \equiv \mathbf{p}-0 \f$ ). With that in mind, real points and
122vector distinguish when the transformation is applied.
Gael Guennebaudf66fe262010-10-19 11:40:49 +0200123<table class="manual">
Gael Guennebaud99462972008-08-31 17:30:09 +0000124<tr><td>
125Apply the transformation to a \b point </td><td>\code
126VectorNf p1, p2;
127p2 = t * p1;\endcode</td></tr>
Gael Guennebaudf66fe262010-10-19 11:40:49 +0200128<tr class="alt"><td>
Gael Guennebaud99462972008-08-31 17:30:09 +0000129Apply the transformation to a \b vector </td><td>\code
130VectorNf vec1, vec2;
131vec2 = t.linear() * vec1;\endcode</td></tr>
132<tr><td>
133Apply a \em general transformation \n to a \b normal \b vector
134(<a href="http://www.cgafaq.info/wiki/Transforming_normals">explanations</a>)</td><td>\code
135VectorNf n1, n2;
136MatrixNf normalMatrix = t.linear().inverse().transpose();
137n2 = (normalMatrix * n1).normalized();\endcode</td></tr>
Gael Guennebaudf66fe262010-10-19 11:40:49 +0200138<tr class="alt"><td>
Gael Guennebaud99462972008-08-31 17:30:09 +0000139Apply a transformation with \em pure \em rotation \n to a \b normal \b vector
140(no scaling, no shear)</td><td>\code
141n2 = t.linear() * n1;\endcode</td></tr>
142<tr><td>
143OpenGL compatibility \b 3D </td><td>\code
144glLoadMatrixf(t.data());\endcode</td></tr>
Gael Guennebaudf66fe262010-10-19 11:40:49 +0200145<tr class="alt"><td>
Gael Guennebaud99462972008-08-31 17:30:09 +0000146OpenGL compatibility \b 2D </td><td>\code
Jitse Niesene0a6ce52011-09-19 21:57:26 +0100147Affine3f aux(Affine3f::Identity());
Benoit Jacob9962c592010-04-22 14:11:18 -0400148aux.linear().topLeftCorner<2,2>() = t.linear();
Gael Guennebaud99462972008-08-31 17:30:09 +0000149aux.translation().start<2>() = t.translation();
150glLoadMatrixf(aux.data());\endcode</td></tr>
151</table>
152
Gael Guennebaudf66fe262010-10-19 11:40:49 +0200153\b Component \b accessors
154<table class="manual">
Gael Guennebaud99462972008-08-31 17:30:09 +0000155<tr><td>
156full read-write access to the internal matrix</td><td>\code
157t.matrix() = matN1xN1; // N1 means N+1
158matN1xN1 = t.matrix();
159\endcode</td></tr>
Gael Guennebaudf66fe262010-10-19 11:40:49 +0200160<tr class="alt"><td>
Gael Guennebaud99462972008-08-31 17:30:09 +0000161coefficient accessors</td><td>\code
162t(i,j) = scalar; <=> t.matrix()(i,j) = scalar;
163scalar = t(i,j); <=> scalar = t.matrix()(i,j);
164\endcode</td></tr>
165<tr><td>
166translation part</td><td>\code
167t.translation() = vecN;
168vecN = t.translation();
169\endcode</td></tr>
Gael Guennebaudf66fe262010-10-19 11:40:49 +0200170<tr class="alt"><td>
Gael Guennebaud99462972008-08-31 17:30:09 +0000171linear part</td><td>\code
172t.linear() = matNxN;
173matNxN = t.linear();
174\endcode</td></tr>
175<tr><td>
176extract the rotation matrix</td><td>\code
Gael Guennebaud8719b1b2012-11-29 22:48:13 +0800177matNxN = t.rotation();
Gael Guennebaud99462972008-08-31 17:30:09 +0000178\endcode</td></tr>
179</table>
180
181
182\b Transformation \b creation \n
183While transformation objects can be created and updated concatenating elementary transformations,
184the Transform class also features a procedural API:
Gael Guennebaudf66fe262010-10-19 11:40:49 +0200185<table class="manual">
Tim Holy16a2d892011-06-20 22:47:58 -0500186<tr><th></th><th>procedural API</th><th>equivalent natural API </th></tr>
Gael Guennebaud99462972008-08-31 17:30:09 +0000187<tr><td>Translation</td><td>\code
188t.translate(Vector_(tx,ty,..));
189t.pretranslate(Vector_(tx,ty,..));
190\endcode</td><td>\code
191t *= Translation_(tx,ty,..);
192t = Translation_(tx,ty,..) * t;
193\endcode</td></tr>
Gael Guennebaudf66fe262010-10-19 11:40:49 +0200194<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
Gael Guennebaud99462972008-08-31 17:30:09 +0000195t.rotate(any_rotation);
196t.prerotate(any_rotation);
197\endcode</td><td>\code
198t *= any_rotation;
199t = any_rotation * t;
200\endcode</td></tr>
201<tr><td>Scaling</td><td>\code
202t.scale(Vector_(sx,sy,..));
203t.scale(s);
204t.prescale(Vector_(sx,sy,..));
205t.prescale(s);
206\endcode</td><td>\code
Gael Guennebaud17273732012-06-18 22:07:13 +0200207t *= Scaling(sx,sy,..);
208t *= Scaling(s);
209t = Scaling(sx,sy,..) * t;
210t = Scaling(s) * t;
Gael Guennebaud99462972008-08-31 17:30:09 +0000211\endcode</td></tr>
Gael Guennebaudf66fe262010-10-19 11:40:49 +0200212<tr class="alt"><td>Shear transformation \n ( \b 2D \b only ! )</td><td>\code
Gael Guennebaud99462972008-08-31 17:30:09 +0000213t.shear(sx,sy);
214t.preshear(sx,sy);
215\endcode</td><td></td></tr>
216</table>
217
218Note that in both API, any many transformations can be concatenated in a single expression as shown in the two following equivalent examples:
Gael Guennebaudf66fe262010-10-19 11:40:49 +0200219<table class="manual">
Gael Guennebaud99462972008-08-31 17:30:09 +0000220<tr><td>\code
221t.pretranslate(..).rotate(..).translate(..).scale(..);
222\endcode</td></tr>
223<tr><td>\code
Gael Guennebaud17273732012-06-18 22:07:13 +0200224t = Translation_(..) * t * RotationType(..) * Translation_(..) * Scaling(..);
Gael Guennebaud99462972008-08-31 17:30:09 +0000225\endcode</td></tr>
226</table>
227
228
229
230<a href="#" class="top">top</a>\section TutorialGeoEulerAngles Euler angles
Gael Guennebaudf66fe262010-10-19 11:40:49 +0200231<table class="manual">
Gael Guennebaud99462972008-08-31 17:30:09 +0000232<tr><td style="max-width:30em;">
233Euler angles might be convenient to create rotation objects.
Tim Holy16a2d892011-06-20 22:47:58 -0500234On the other hand, since there exist 24 different conventions, they are pretty confusing to use. This example shows how
Gael Guennebaud99462972008-08-31 17:30:09 +0000235to create a rotation matrix according to the 2-1-2 convention.</td><td>\code
236Matrix3f m;
237m = AngleAxisf(angle1, Vector3f::UnitZ())
238* * AngleAxisf(angle2, Vector3f::UnitY())
239* * AngleAxisf(angle3, Vector3f::UnitZ());
240\endcode</td></tr>
241</table>
242
Gael Guennebaud41ea92d2010-07-04 10:14:47 +0200243\li \b Next: \ref TutorialSparse
244
Gael Guennebaud99462972008-08-31 17:30:09 +0000245*/
246
247}