2008-09-01 01:30:09 +08:00
namespace Eigen {
2013-01-07 06:48:59 +08:00
/** \eigenManualPage TutorialGeometry Space transformations
2008-09-01 01:30:09 +08:00
2013-01-07 06:48:59 +08:00
In 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.
2008-09-01 01:30:09 +08:00
Big changes in Eigen documentation:
- Organize the documentation into "chapters".
- Each chapter include many documentation pages, reference pages organized as modules, and a quick reference page.
- The "Chapters" tree is created using the defgroup/ingroup mechanism, even for the documentation pages (i.e., .dox files for which I added an \eigenManualPage macro that we can switch between \page or \defgroup ).
- Add a "General topics" entry for all pages that do not fit well in the previous "chapters".
- The highlevel struture is managed by a new eigendoxy_layout.xml file.
- remove the "index" and quite useless pages (namespace list, class hierarchy, member list, file list, etc.)
- add the javascript search-engine.
- add the "treeview" panel.
- remove \tableofcontents (replace them by a custom \eigenAutoToc macro to be able to easily re-enable if needed).
- add javascript to automatically generate a TOC from the h1/h2 tags of the current page, and put the TOC in the left side panel.
- overload various javascript function generated by doxygen to:
- remove the root of the treeview
- remove links to section/subsection from the treeview
- automatically expand the "Chapters" section
- automatically expand the current section
- adjust the height of the treeview to take into account the TOC
- always use the default .css file, eigendoxy.css now only includes our modifications
- use Doxyfile to specify our logo
- remove cross references to unsupported modules (temporarily)
2013-01-05 23:37:11 +08:00
\eigenAutoToc
2008-09-01 01:30:09 +08:00
2008-12-23 04:50:47 +08:00
Eigen's Geometry module provides two different kinds of geometric transformations:
- 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.
2010-07-04 16:14:47 +08:00
- Projective or affine transformation matrices: see the Transform class. These are really matrices.
2008-12-23 04:50:47 +08:00
2010-08-18 02:03:50 +08:00
\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.
2008-12-23 04:50:47 +08:00
You can construct a Transform from an abstract transformation, like this:
\code
Transform t(AngleAxis(angle,axis));
\endcode
or like this:
\code
Transform t;
t = AngleAxis(angle,axis);
\endcode
But note that unfortunately, because of how C++ works, you can \b not do this:
\code
Transform t = AngleAxis(angle,axis);
\endcode
<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.
</span>
2008-09-01 01:30:09 +08:00
\section TutorialGeoElementaryTransformations Transformation types
2010-10-19 17:40:49 +08:00
<table class="manual">
<tr><th>Transformation type</th><th>Typical initialization code</th></tr>
2008-09-01 01:30:09 +08:00
<tr><td>
2008-09-01 14:33:19 +08:00
\ref Rotation2D "2D rotation" from an angle</td><td>\code
2008-09-01 01:30:09 +08:00
Rotation2D<float> rot2(angle_in_radian);\endcode</td></tr>
2010-10-19 17:40:49 +08:00
<tr class="alt"><td>
2008-09-01 14:33:19 +08:00
3D rotation as an \ref AngleAxis "angle + axis"</td><td>\code
2011-11-01 16:40:51 +08:00
AngleAxis<float> aa(angle_in_radian, Vector3f(ax,ay,az));\endcode
<span class="note">The axis vector must be normalized.</span></td></tr>
2008-09-01 01:30:09 +08:00
<tr><td>
2008-09-01 14:33:19 +08:00
3D rotation as a \ref Quaternion "quaternion"</td><td>\code
2011-05-29 04:12:15 +08:00
Quaternion<float> q; q = AngleAxis<float>(angle_in_radian, axis);\endcode</td></tr>
2010-10-19 17:40:49 +08:00
<tr class="alt"><td>
2008-09-01 01:30:09 +08:00
N-D Scaling</td><td>\code
2012-06-19 04:07:13 +08:00
Scaling(sx, sy)
Scaling(sx, sy, sz)
Scaling(s)
Scaling(vecN)\endcode</td></tr>
2008-09-01 01:30:09 +08:00
<tr><td>
N-D Translation</td><td>\code
Translation<float,2>(tx, ty)
Translation<float,3>(tx, ty, tz)
Translation<float,N>(s)
Translation<float,N>(vecN)\endcode</td></tr>
2010-10-19 17:40:49 +08:00
<tr class="alt"><td>
2008-09-01 01:30:09 +08:00
N-D \ref TutorialGeoTransform "Affine transformation"</td><td>\code
2010-10-06 19:27:14 +08:00
Transform<float,N,Affine> t = concatenation_of_any_transformations;
2012-06-19 04:07:13 +08:00
Transform<float,3,Affine> t = Translation3f(p) * AngleAxisf(a,axis) * Scaling(s);\endcode</td></tr>
2008-09-01 01:30:09 +08:00
<tr><td>
N-D Linear transformations \n
<em class=note>(pure rotations, \n scaling, etc.)</em></td><td>\code
Matrix<float,N> t = concatenation_of_rotations_and_scalings;
2012-06-19 04:07:13 +08:00
Matrix<float,2> t = Rotation2Df(a) * Scaling(s);
Matrix<float,3> t = AngleAxisf(a,axis) * Scaling(s);\endcode</td></tr>
2008-09-01 01:30:09 +08:00
</table>
<strong>Notes on rotations</strong>\n To transform more than a single vector the preferred
representations are rotation matrices, while for other usages Quaternion is the
representation of choice as they are compact, fast and stable. Finally Rotation2D and
AngleAxis are mainly convenient types to create other rotation objects.
2011-06-21 11:47:58 +08:00
<strong>Notes on Translation and Scaling</strong>\n Like AngleAxis, these classes were
2008-09-01 01:30:09 +08:00
designed to simplify the creation/initialization of linear (Matrix) and affine (Transform)
transformations. Nevertheless, unlike AngleAxis which is inefficient to use, these classes
might still be interesting to write generic and efficient algorithms taking as input any
kind of transformations.
Any of the above transformation types can be converted to any other types of the same nature,
2008-11-23 03:51:05 +08:00
or to a more generic type. Here are some additional examples:
2010-10-19 17:40:49 +08:00
<table class="manual">
2008-09-01 01:30:09 +08:00
<tr><td>\code
2011-05-29 04:12:15 +08:00
Rotation2Df r; r = Matrix2f(..); // assumes a pure rotation matrix
AngleAxisf aa; aa = Quaternionf(..);
AngleAxisf aa; aa = Matrix3f(..); // assumes a pure rotation matrix
Matrix2f m; m = Rotation2Df(..);
2012-06-19 04:07:13 +08:00
Matrix3f m; m = Quaternionf(..); Matrix3f m; m = Scaling(..);
Affine3f m; m = AngleAxis3f(..); Affine3f m; m = Scaling(..);
2011-05-29 04:12:15 +08:00
Affine3f m; m = Translation3f(..); Affine3f m; m = Matrix3f(..);
2008-09-01 01:30:09 +08:00
\endcode</td></tr>
</table>
<a href="#" class="top">top</a>\section TutorialGeoCommontransformationAPI Common API across transformation types
2009-02-06 05:19:40 +08:00
To some extent, Eigen's \ref Geometry_Module "geometry module" allows you to write
2008-09-01 01:30:09 +08:00
generic algorithms working on any kind of transformation representations:
2010-10-19 17:40:49 +08:00
<table class="manual">
2008-09-01 01:30:09 +08:00
<tr><td>
Concatenation of two transformations</td><td>\code
gen1 * gen2;\endcode</td></tr>
2010-10-19 17:40:49 +08:00
<tr class="alt"><td>Apply the transformation to a vector</td><td>\code
2008-09-01 01:30:09 +08:00
vec2 = gen1 * vec1;\endcode</td></tr>
<tr><td>Get the inverse of the transformation</td><td>\code
gen2 = gen1.inverse();\endcode</td></tr>
2010-10-19 17:40:49 +08:00
<tr class="alt"><td>Spherical interpolation \n (Rotation2D and Quaternion only)</td><td>\code
2008-09-01 01:30:09 +08:00
rot3 = rot1.slerp(alpha,rot2);\endcode</td></tr>
</table>
<a href="#" class="top">top</a>\section TutorialGeoTransform Affine transformations
2018-08-02 09:34:47 +08:00
Generic affine transformations are represented by the Transform class which internally
2008-09-01 01:30:09 +08:00
is a (Dim+1)^2 matrix. In Eigen we have chosen to not distinghish between points and
vectors such that all points are actually represented by displacement vectors from the
origin ( \f$ \mathbf{p} \equiv \mathbf{p}-0 \f$ ). With that in mind, real points and
vector distinguish when the transformation is applied.
2010-10-19 17:40:49 +08:00
<table class="manual">
2008-09-01 01:30:09 +08:00
<tr><td>
Apply the transformation to a \b point </td><td>\code
VectorNf p1, p2;
p2 = t * p1;\endcode</td></tr>
2010-10-19 17:40:49 +08:00
<tr class="alt"><td>
2008-09-01 01:30:09 +08:00
Apply the transformation to a \b vector </td><td>\code
VectorNf vec1, vec2;
vec2 = t.linear() * vec1;\endcode</td></tr>
<tr><td>
2015-09-07 17:08:41 +08:00
Apply a \em general transformation \n to a \b normal \b vector \n
</td><td>\code
2008-09-01 01:30:09 +08:00
VectorNf n1, n2;
MatrixNf normalMatrix = t.linear().inverse().transpose();
n2 = (normalMatrix * n1).normalized();\endcode</td></tr>
2015-09-07 17:08:41 +08:00
<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>
2010-10-19 17:40:49 +08:00
<tr class="alt"><td>
2008-09-01 01:30:09 +08:00
Apply a transformation with \em pure \em rotation \n to a \b normal \b vector
(no scaling, no shear)</td><td>\code
n2 = t.linear() * n1;\endcode</td></tr>
<tr><td>
OpenGL compatibility \b 3D </td><td>\code
glLoadMatrixf(t.data());\endcode</td></tr>
2010-10-19 17:40:49 +08:00
<tr class="alt"><td>
2008-09-01 01:30:09 +08:00
OpenGL compatibility \b 2D </td><td>\code
2011-09-20 04:57:26 +08:00
Affine3f aux(Affine3f::Identity());
2010-04-23 02:11:18 +08:00
aux.linear().topLeftCorner<2,2>() = t.linear();
2008-09-01 01:30:09 +08:00
aux.translation().start<2>() = t.translation();
glLoadMatrixf(aux.data());\endcode</td></tr>
</table>
2010-10-19 17:40:49 +08:00
\b Component \b accessors
<table class="manual">
2008-09-01 01:30:09 +08:00
<tr><td>
full read-write access to the internal matrix</td><td>\code
t.matrix() = matN1xN1; // N1 means N+1
matN1xN1 = t.matrix();
\endcode</td></tr>
2010-10-19 17:40:49 +08:00
<tr class="alt"><td>
2008-09-01 01:30:09 +08:00
coefficient accessors</td><td>\code
t(i,j) = scalar; <=> t.matrix()(i,j) = scalar;
scalar = t(i,j); <=> scalar = t.matrix()(i,j);
\endcode</td></tr>
<tr><td>
translation part</td><td>\code
t.translation() = vecN;
vecN = t.translation();
\endcode</td></tr>
2010-10-19 17:40:49 +08:00
<tr class="alt"><td>
2008-09-01 01:30:09 +08:00
linear part</td><td>\code
t.linear() = matNxN;
matNxN = t.linear();
\endcode</td></tr>
<tr><td>
extract the rotation matrix</td><td>\code
2012-11-29 22:48:13 +08:00
matNxN = t.rotation();
2008-09-01 01:30:09 +08:00
\endcode</td></tr>
</table>
\b Transformation \b creation \n
While transformation objects can be created and updated concatenating elementary transformations,
the Transform class also features a procedural API:
2010-10-19 17:40:49 +08:00
<table class="manual">
2011-06-21 11:47:58 +08:00
<tr><th></th><th>procedural API</th><th>equivalent natural API </th></tr>
2008-09-01 01:30:09 +08:00
<tr><td>Translation</td><td>\code
t.translate(Vector_(tx,ty,..));
t.pretranslate(Vector_(tx,ty,..));
\endcode</td><td>\code
t *= Translation_(tx,ty,..);
t = Translation_(tx,ty,..) * t;
\endcode</td></tr>
2010-10-19 17:40:49 +08:00
<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
2008-09-01 01:30:09 +08:00
t.rotate(any_rotation);
t.prerotate(any_rotation);
\endcode</td><td>\code
t *= any_rotation;
t = any_rotation * t;
\endcode</td></tr>
<tr><td>Scaling</td><td>\code
t.scale(Vector_(sx,sy,..));
t.scale(s);
t.prescale(Vector_(sx,sy,..));
t.prescale(s);
\endcode</td><td>\code
2012-06-19 04:07:13 +08:00
t *= Scaling(sx,sy,..);
t *= Scaling(s);
t = Scaling(sx,sy,..) * t;
t = Scaling(s) * t;
2008-09-01 01:30:09 +08:00
\endcode</td></tr>
2010-10-19 17:40:49 +08:00
<tr class="alt"><td>Shear transformation \n ( \b 2D \b only ! )</td><td>\code
2008-09-01 01:30:09 +08:00
t.shear(sx,sy);
t.preshear(sx,sy);
\endcode</td><td></td></tr>
</table>
Note that in both API, any many transformations can be concatenated in a single expression as shown in the two following equivalent examples:
2010-10-19 17:40:49 +08:00
<table class="manual">
2008-09-01 01:30:09 +08:00
<tr><td>\code
t.pretranslate(..).rotate(..).translate(..).scale(..);
\endcode</td></tr>
<tr><td>\code
2012-06-19 04:07:13 +08:00
t = Translation_(..) * t * RotationType(..) * Translation_(..) * Scaling(..);
2008-09-01 01:30:09 +08:00
\endcode</td></tr>
</table>
<a href="#" class="top">top</a>\section TutorialGeoEulerAngles Euler angles
2010-10-19 17:40:49 +08:00
<table class="manual">
2008-09-01 01:30:09 +08:00
<tr><td style="max-width:30em;">
Euler angles might be convenient to create rotation objects.
2011-06-21 11:47:58 +08:00
On the other hand, since there exist 24 different conventions, they are pretty confusing to use. This example shows how
2008-09-01 01:30:09 +08:00
to create a rotation matrix according to the 2-1-2 convention.</td><td>\code
Matrix3f m;
m = AngleAxisf(angle1, Vector3f::UnitZ())
2015-09-07 17:08:41 +08:00
* AngleAxisf(angle2, Vector3f::UnitY())
* AngleAxisf(angle3, Vector3f::UnitZ());
2008-09-01 01:30:09 +08:00
\endcode</td></tr>
</table>
*/
}