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