Eigen教程 - 官方文档翻译

概览 Overview

todo

开始 Getting started

todo

章节 Chapters

稠密矩阵和向量操作 Dense matrix and array manipulation

todo

稠密线性问题和分解Dense linear problems and decompositions

todo

稀疏线性代数Sparse linear algebra

todo

几何Geometry

空间变换Space transformations

在本页中,我们将介绍几何模块提供的处理2D和3D旋转以及投影或仿射变换的多种可能方法。
Eigen的Geometry模块提供两种不同的几何变换方法:

  • 抽象变换,例如旋转(由角度和轴或四元数表示)、平移、缩放。这些转换不是用矩阵表示的,但您仍然可以在表达式中将它们与矩阵和向量混合,并根据需要将它们转换为矩阵。
  • 投影或仿射变换矩阵:请参见Transform类。这些实际上是矩阵。
    注意:如果您正在使用OpenGL 4x4矩阵,那么Affine3f和Affine3d就是您想要的。由于Eigen默认为列主存储,因此可以直接使用Transform::data()方法将转换矩阵传递给OpenGL。

你可以从一个抽象转换创建一个Transform对象,就像这样:

Transform t(AngleAxis(angle,axis));

或者像这样:

Transform t;
t = AngleAxis(angle,axis);

但请注意,不幸的是,由于C++的工作原理,您不能这样做:

Transform t = AngleAxis(angle,axis);

说明:在C++语言中,这需要Transform具有来自AngleAxis的非显式转换构造函数,但我们确实不想在这里允许隐式转换。

转换类型 Transformation types

转换类型 典型初始化代码
2D旋转 Rotation2D<float> rot2(angle_in_radian);
3D旋转(角度+轴) AngleAxis<float> aa(angle_in_radian, Vector3f(ax,ay,az)); 轴向量必须归一化
3D旋转(四元数) Quaternion<float> q; q = AngleAxis<float>(angle_in_radian, axis);
N-D 缩放 Scaling(sx, sy);
Scaling(sx, sy, sz);
Scaling(s);
Scaling(vecN)
N-D 平移 Translation<float,2>(tx, ty);
Translation<float,3>(tx, ty, tz);
Translation<float,N>(s);
Translation<float,N>(vecN)
N-D 仿射变换 Transform<float,N,Affine> t = concatenation_of_any_transformations;
Transform<float,3,Affine> t = Translation3f(p) * AngleAxisf(a,axis) * Scaling(s);
N-D 线性变换(纯旋转、缩放等) Matrix<float,N> t = concatenation_of_rotations_and_scalings;
Matrix<float,2> t = Rotation2Df(a) * Scaling(s);
Matrix<float,3> t = AngleAxisf(a,axis) * Scaling(s);

旋转的注释:要转换多个向量,首选的表示是旋转矩阵,而对于其他用途,四元数是首选的表示,因为它们紧凑、快速且稳定。最后,Rotation2D和AngleAxis是创建其他旋转对象的主要方便类型。

平移和缩放注释:与AngleAxis一样,这些类旨在简化线性(矩阵)和仿射(变换)变换的创建/初始化。然而,与使用效率低下的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 Common API across transformation types

在某种程度上,Eigen的几何模块允许您编写处理任何类型变换表示的通用算法:

  1. 变换的级联:gen1 * gen2;
  2. 对向量的变换: vec2 = gen1 * vec1;
  3. 获取变换的逆:gen2 = gen1.inverse();
  4. 球面插值(仅限旋转2D和四元数):rot3 = rot1.slerp(alpha,rot2);

仿射变换 Affine transformations

泛型仿射变换由Transform类表示,该类内部是一个(Dim+1)^2矩阵。在Eigen中,我们选择不区分点和向量,这样所有点实际上都由原点的位移向量表示(p≡p−0 ). 考虑到这一点,在应用变换时,实点和矢量是可以区分的。

  • 将变换应用到点上:
VectorNf p1, p2;
p2 = t * p1;
  • 将变换应用在向量上
VectorNf vec1, vec2;
vec2 = t.linear() * vec1;
  • 对法向量应用一般变换
VectorNf n1, n2;
MatrixNf normalMatrix = t.linear().inverse().transpose();
n2 = (normalMatrix * n1).normalized();
  • 对法向量应用纯旋转变换(无缩放,无剪切)
n2 = t.linear() * n1;
  • 兼容OpenGL的3D变化
 	
glLoadMatrixf(t.data());
  • 兼容OpenGL的2D变化
Affine3f aux(Affine3f::Identity());
aux.linear().topLeftCorner<2,2>() = t.linear();
aux.translation().start<2>() = t.translation();
glLoadMatrixf(aux.data());
组件访问权限
  • 内部矩阵的完全读写权限
t.matrix() = matN1xN1;    // N1 means N+1
matN1xN1 = t.matrix();
  • 系数访问
t(i,j) = scalar;   <=>   t.matrix()(i,j) = scalar;
scalar = t(i,j);   <=>   scalar = t.matrix()(i,j);
  • 平移部分
t.translation() = vecN;
vecN = t.translation();
  • 线性部分
t.linear() = matNxN;
matNxN = t.linear();
  • 提取出旋转矩阵
matNxN = t.rotation();
变换的创建

虽然可以创建和更新连接基本转换的转换对象,但Transform类还具有一个过程API:

操作 过程API 等效的原生API
平移 t.translate(Vector_(tx,ty,..));
t.pretranslate(Vector_(tx,ty,..));
t *= Translation_(tx,ty,..);
t = Translation_(tx,ty,..) * t;
旋转 t.rotate(any_rotation);
t.prerotate(any_rotation);
t *= Translation_(tx,ty,..);
t = any_rotation * t;
缩放 t.scale(Vector_(sx,sy,..));
t.scale(s);
t.prescale(Vector_(sx,sy,..));
t.prescale(s);
t *= Scaling(sx,sy,..);
t *= Scaling(s);
t = Scaling(sx,sy,..) * t;
t = Scaling(s) * t;
剪切 t.shear(sx,sy);
t.preshear(sx,sy);
请注意,在这两个API中,任何多个转换都可以在单个表达式中串联,如以下两个等效示例所示:
t.pretranslate(..).rotate(..).translate(..).scale(..);
t = Translation_(..) * t * RotationType(..) * Translation_(..) * Scaling(..);

欧拉角Euler angles

Euler角度可以方便地创建旋转对象。另一方面,由于存在24种不同的约定,因此使用起来相当混乱。此示例显示如何根据2-1-2约定创建旋转矩阵。

Matrix3f m;
m = AngleAxisf(angle1, Vector3f::UnitZ())
    * AngleAxisf(angle2, Vector3f::UnitY())
    * AngleAxisf(angle3, Vector3f::UnitZ());

Extending/Customizing Eigen
General topics
Class List

posted @ 2022-10-08 18:19  loufand  阅读(947)  评论(0编辑  收藏  举报