Eigen3:无需存储w分量实现Matrix4d与连续Vector3d相乘
Eigen3中3D向量与4x4矩阵乘法的空间优化方案
问题场景
使用Eigen3处理连续存储的多个Vector3d时,需要与Matrix4d进行乘法运算,但直接操作会遇到矩阵尺寸不匹配的问题。此前的解决方式是在磁盘存储时为每个向量添加w分量转为Vector4d,但希望节省每个向量占用的1个double空间,现有代码如下:
#include <array> #include <eigen3/Eigen/Geometry> #include <iostream> using namespace std; #define M 4 int main (){ #if M == 4 auto arr = std::to_array( {1., 2., 3., 1., 4., 5., 6., 1.} ); Eigen::Map<Eigen::MatrixXd> v( arr.data(), 4, 2 ); #elif M == 3 auto arr = std::to_array( {1., 2., 3., 4., 5., 6.} ); Eigen::Map<Eigen::MatrixXd> v( arr.data(), 3, 2 ); #endif // 示例变换矩阵,实际代码中为参数传入的不同矩阵 Eigen::Matrix4d w; w.setIdentity(); w( 0, 3 ) = 10; w( 1, 3 ) = 20; cout << v.matrix() << "\n\n"; cout << w.matrix() << "\n\n"; auto res = w * v; std::cout << res.matrix() << std::endl; }
解决方案:无需存储w分量,Eigen可自动计算
不需要额外存储w分量,利用Eigen的块操作与广播特性就能完成计算,完全避免空间浪费,分两种场景处理:
1. 针对仿射变换(绝大多数3D变换场景)
如果你的Matrix4d是仿射变换矩阵(最后一行为[0, 0, 0, 1],包含平移、旋转、缩放等常见3D变换),可以直接拆解矩阵运算,跳过w分量的存储:
原理是齐次坐标下的仿射变换展开后,等价于线性变换加平移向量,无需显式构造齐次向量。修改后的代码如下:
#include <array> #include <eigen3/Eigen/Geometry> #include <iostream> using namespace std; #define M 3 int main (){ #if M == 4 auto arr = std::to_array( {1., 2., 3., 1., 4., 5., 6., 1.} ); Eigen::Map<Eigen::MatrixXd> v( arr.data(), 4, 2 ); #elif M == 3 auto arr = std::to_array( {1., 2., 3., 4., 5., 6.} ); Eigen::Map<Eigen::MatrixXd> v( arr.data(), 3, 2 ); #endif Eigen::Matrix4d w; w.setIdentity(); w( 0, 3 ) = 10; w( 1, 3 ) = 20; cout << v.matrix() << "\n\n"; cout << w.matrix() << "\n\n"; Eigen::MatrixXd res; #if M == 4 res = w * v; #elif M == 3 // 直接计算仿射变换结果,无需存储w分量 res = w.topLeftCorner<3,3>() * v + w.col(3).replicate(1, v.cols()); // 若需要输出齐次坐标形式(4xN),可按需构造: // Eigen::MatrixXd res_homo(4, v.cols()); // res_homo.topRows<3>() = res; // res_homo.row(3).setOnes(); #endif std::cout << res.matrix() << std::endl; }
2. 针对非仿射变换(极少场景)
如果你的Matrix4d不是仿射矩阵(最后一行非[0,0,0,1]),则必须明确每个向量的w分量才能完成正确的齐次坐标运算,这种情况下才需要存储w分量。但这类场景在3D空间变换中非常罕见。
内容的提问来源于stack exchange,提问作者Kroma
相关产品推荐
相关产品推荐

