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