在Eigen中将变换应用于包含向量的矩阵的较短方法?

时间:2016-08-09 03:34:56

标签: c++ eigen

是否有更短的方法来应用转换?

auto vecs = Matrix<float, Dynamic, 3>(); //vector in each row.
Affine3f transform = ...; // some Affine3 transform

for (int r = 0; r < vecs.rows(); r++) {
    Vector3f v = vecs.row(r);
    v = transform * v;
    vecs.row(r) = v;
}

3 个答案:

答案 0 :(得分:1)

@ JE42是对的,因为Eigen几乎不需要循环。 当然可以简化。但请注意,您的案例中的transform * v不是简单的乘法,而是等同于transform.linear() * v + transform.translation()的仿射变换。 https://eigen.tuxfamily.org/dox-devel/group__TutorialGeometry.html

此外,您的“积分”是行,因此需要额外的转置。

总之,(没有实际编译或测试)你的计算应该等同于

vecs.transpose() = (transform.linear() * vecs.transpose()).array() + transform.translation();

答案 1 :(得分:1)

您可以直接将Affine变换应用于存储在矩阵中的一组列向量。由于矢量按行排列,因此需要转置矩阵。因此,你的for循环减少到:

vecs.transpose() = transform * vecs.transpose();

答案 2 :(得分:0)

以下代码对我有用。它取自这个tutorial。 上面提供的解决方案对我不起作用。不过我没有像 OP 那样转置矩阵。

代码如下:

#include <Eigen/Core>
#include <Eigen/Geometry>
#include <iostream>


using namespace std;
using namespace Eigen;

int main() {
    float arrVertices[] = { -1.0 , -1.0 , -1.0 ,
    1.0 , -1.0 , -1.0 ,
    1.0 , 1.0 , -1.0 ,
    -1.0 , 1.0 , -1.0 ,
    -1.0 , -1.0 , 1.0 ,
    1.0 , -1.0 , 1.0 ,
    1.0 , 1.0 , 1.0 ,
    -1.0 , 1.0 , 1.0 };

    MatrixXf mVertices = Map < Matrix <float, 3, 8 > >(arrVertices);
    Transform <float, 3, Affine > t = Transform <float, 3, Affine >::Identity();
    t.scale(0.8f);

    t.rotate(AngleAxisf(0.25f * EIGEN_PI, Vector3f::UnitX()));

    t.translate(Vector3f(1.5, 10.2, -5.1));
    cout << t * mVertices.colwise().homogeneous() << endl;
}

请注意,我使用的是 EIGEN_PI 而不是原始文档中使用的 M_PI。

引用文档中的这个描述也应该有助于理解代码的最后一行:“看看如何将顶点存储为矩阵的列允许我们使用单个矩阵乘法来转换所有顶点。但是,要做到这一点,变换矩阵的内部维度,顶点矩阵必须匹配。t 使用齐次坐标,因此 3 维变换表示为 4x4 矩阵。为了匹配这些维度,我们对顶点矩阵的每一列进行齐次化 通过使用 colwise() 方法。"