Search code examples
c++eigeneigen3

How to apply affine2d transform onto a block of 3d matrix?


I have a matrix (x, y, z each column), and only want to perform 2D transform onto x and y axis, ignoring z. It seems affine2d can't multiply with block, is there any other way to make it work?

Eigen::matrix<double, 3, 4> x3d;
x3d <<
  1, 2, 3, 4,
  2, 3, 4, 5,
  1, 1, 1, 1;
auto x2d = x3d.topRows(2);
Eigen::Affine2d T = Eigen::Translation2d(1, 2) * Eigen::Scaling(1., 2.);
x2d = T*x2d;

output error:

> /home/lei/Work/SurfTomo/./include/Eigen/src/Geometry/Transform.h:1361:5:
> error: static_assert failed "YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES"
>     EIGEN_STATIC_ASSERT(OtherRows==Dim, YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES);
>     ^                   ~~~~~~~~~~~~~~ /home/lei/Work/SurfTomo/./include/Eigen/src/Core/util/StaticAssert.h:32:40:
> note: expanded from macro 'EIGEN_STATIC_ASSERT'
>     #define EIGEN_STATIC_ASSERT(X,MSG) static_assert(X,#MSG);
>                                        ^             ~ /home/lei/Work/SurfTomo/./include/Eigen/src/Geometry/Transform.h:442:77:
> note: in instantiation of member function
>       'Eigen::internal::transform_right_product_impl<Eigen::Transform<double,
> 2, 2, 0>, Eigen::Block<Eigen::Matrix<double, 3, 4, 0, 3, 4>, -1, 4,
>       false>, 2, 4>::run' requested here   { return internal::transform_right_product_impl<Transform,
> OtherDerived>::run(*this,other.derived()); }
>                                                                             ^ /home/lei/Work/SurfTomo/test/test_3dto2d.cc:27:10: note: in
> instantiation of function template specialization
> 'Eigen::Transform<double, 2, 2,
>       0>::operator*<Eigen::Block<Eigen::Matrix<double, 3, 4, 0, 3, 4>, -1, 4, false> >' requested here   x2d = T*x2d;
>          ^ 1 error generated.

I find the codes below can solve this problem, though I don't understand why it works.

x2d = T * x2d.colwise().homogeneous();

Solution

  • When multiplying with Eigen::Affine2d, Eigen wants to know the number of rows of the other matrix at compile time (because depending on that, different code paths are taken, and run-time checks can make a significant overhead here).

    Just create your x2d matrix using

    auto x2d = x3d.topRows<2>();