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