法线向量计算及z轴旋转后点z值不一致问题排查
问题描述
我有三个点,通过以下代码获取:
auto it = vectorList.begin(); Eigen::Vector3d point1 = *it++; Eigen::Vector3d point2 = *it++; Eigen::Vector3d point3 = *it;
我用这三个点创建平面并获取其法线向量:
Eigen::Hyperplane<double, 3> plane = Eigen::Hyperplane<double, 3>::Through(point1, point2, point3); Eigen::Vector3d normalVector = plane.normal(); normalVector = normalVector.normalized();
我计算法线向量与z轴的夹角,以此生成绕x轴的旋转矩阵,期望旋转后三个点的z值一致:
double anglezaxis; anglezaxis = std::atan2(normalVector.x(), normalVector.z()); Eigen::AngleAxisd rotation(anglezaxis, Eigen::Vector3d::UnitX()); point1 = rotation*point1; point2 = rotation *point2; point3 = rotation * point3; qDebug() << point1.z() << point2.z() << point3.z();
但实际旋转后三个点的z值差异极大,请问我的思路存在什么错误?
错误分析与修正
旋转轴选择不完整:要让三点z值一致,需让平面与XY平面平行(即平面法线完全对齐Z轴)。仅绕X轴旋转只能处理法线在X-Z平面的分量,无法消除法线的Y分量。只要法线存在Y方向分量,旋转后的平面仍会倾斜,三点z值必然存在差异。
夹角计算逻辑错误:
std::atan2(normalVector.x(), normalVector.z())计算的是法线在X-Z平面的投影与Z轴的夹角,这个角度对应的旋转无法让法线完全对齐Z轴,自然达不到让平面水平的目的。
修正方案
直接计算从当前法线到Z轴的旋转,用Eigen的四元数可以一步完成:
Eigen::Vector3d target_normal = Eigen::Vector3d::UnitZ(); // 生成从原法线到目标法线的旋转四元数 Eigen::Quaterniond rotation = Eigen::Quaterniond::FromTwoVectors(normalVector, target_normal); point1 = rotation * point1; point2 = rotation * point2; point3 = rotation * point3;
这样旋转后,三点所在平面与XY平面平行,z值会完全一致。
内容的提问来源于stack exchange,提问作者meno
相关产品推荐
相关产品推荐

