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