Gemometry 几何模块
在本页中,我们将介绍几何模块提供的多种可能性来处理 2D 和 3D 旋转以及投影或仿射变换。
Eigen 的几何模块提供了两种不同类型的几何变换:
- 抽象变换,例如旋转(由角度和轴或四元数表示)、平移、缩放。这些转换不表示为矩阵,但您仍然可以将它们与表达式中的矩阵和向量混合,并根据需要将它们转换为矩阵。
- 投影或仿射变换矩阵:参见 Transform 类。 这些确实是矩阵。
注意 如果您使用的是 OpenGL 4x4 矩阵,那么 Affine3f 和 Affine3d 就是您想要的。 由于 Eigen 默认以列为主存储,您可以直接使用 Transform::data() 方法将您的转换矩阵传递给 OpenGL。
可以通过如下方式构造一个 Transform 类型:
Transform t(AngleAxis(angle, axis)); // 注意 Transform 和 AngleAxis 实际使用时需要确定类型
Transform t;
t = AngleAxis(angle, axis);
但是下面的方式不能构造一个 Transform 类型,因为下面的方式需要 AngleAxis
提供一个 non-explicit
的转换构造函数,但是我们并不希望在这里发生一个隐式转换(implicit casting)。
Transform t = AngleAxis(angle, axis));
Transformation types
转换类型 | 初始化代码 |
---|---|
从角度式构建二维旋转 | Rotation2D<float> rot2(angle_in_radian); |
从等效旋转矢量构建三维旋转 | AngleAxisf aa(angle_in_radian, Vector3f(ax,ay,az)); |
从四元数构建三维旋转 | Quaternion<float> q; q = AngleAxis<float>(angle_in_radian, axis); |
N维缩放 | Scaling(sx, sy); Scaling(sx, sy, sz); Scaling(s); Scaling(vecN) |
N维平移 | Translation<float,2>(tx,ty); Translation<float,3>(tx, ty, tz); Translation<float,N>(s); Translation<float,N>(vecN) |
N维仿射变换 | Tranform<float, 3, Affine> t = Translation3f(p) * AngleAxisf(a, axis) * Scaling(s); |
N维线性变换 (纯旋转、缩放等) | Matrix<float, 3> t = AngleAxisf(a, axis) * Scaling(s); |
注意!
AngleAxis
从实际效果上来看就是等效旋转矢量。在构建时需要保证Vector
是一个单位向量
关于旋转的注意事项:
要转换多个向量,首选的表示是旋转矩阵,而对于其他用途,四元数是首选的表示,因为它们紧凑、快速且稳定。 最后 Rotation2D
和 AngleAxis
主要是方便创建其他旋转对象的类型。
平移和缩放注意事项
与 AngleAxis
类似,Translation
、Scanling
等类旨在简化线性(矩阵)和仿射(变换)变换的创建/初始化。 然而,与使用效率低下的 AngleAxis
不同,这些类对于编写将任何类型的转换作为输入的通用且高效的算法可能仍然很有趣。
上述任何转换类型都可以转换为具有相同性质的任何其他类型,或者转换为更通用的类型。 以下是一些额外的例子:
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(..);
Matrix3f m; m = Quaternionf(..); Matrix3f m; m = Scaling(..);
Affine3f m; m = AngleAxis3f(..); Affine3f m; m = Scaling(..);
Affine3f m; m = Translation3f(..); Affine3f m; m = Matrix3f(..);
跨变换类型的通用 API
在某种程度上,Eigen 的几何模块允许您编写处理任何类型的变换表示的通用算法:
连续的两个变换 | gen1 * gen2; |
将变换应用于向量 | vec2 = gen1 * vec1; |
得到逆变换 | gen2 = gen1.inverse(); |
球面插值 (仅限 Rotation2D 和四元数) | rot3 = rot1.slerp(alpha, rot2); |
仿射变换
有待补充
欧拉角
欧拉角可能便于创建旋转对象。 另一方面,由于存在 24 种不同的约定,因此使用起来非常混乱。 此示例显示如何根据 2-1-2 和2-1-0 的约定顺序创建旋转矩阵
Matrix3f m; // 2-1-2
m = AngleAxisf(angle1, Vector3f::UnitZ())
* AngleAxisf(angle2, Vector3f::UnitY())
* AngleAxisf(angle3, Vector3f::UnitZ());
Matrix3f m1; // 2-1-0
m1 = AngleAxisf(angle1, Vector3f::UnitZ())
* AngleAxisf(angle2, Vector3f::UnitY())
* AngleAxisf(angle3, Vector3f::UnitX());