成都网站建设赢展,怎样建设尧都水果网站,wordpress 按字段排序,游戏开发工资假设你有一组 3D 中的 n 个点#xff0c;并且想要为它们拟合一个平面。 在本文中#xff0c;我将推导出一个简单的、数值稳定的方法#xff0c;并提供它的源代码。 听起来很好玩#xff1f; 我们开始吧#xff01; NSDT工具推荐#xff1a; Three.js AI纹理开发包 - YOLO…假设你有一组 3D 中的 n 个点并且想要为它们拟合一个平面。 在本文中我将推导出一个简单的、数值稳定的方法并提供它的源代码。 听起来很好玩 我们开始吧 NSDT工具推荐 Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器 - REVIT导出3D模型插件 - 3D模型语义搜索引擎 首先如果在网上寻找答案你将得到的答案包括对协方差矩阵进行奇异值分解以找到最小特征值的特征向量。 然而事实证明这让事情变得比他们需要的更加复杂。 让我们从基础开始
平面通常由法向量 n [a, b, c]ᵀ 和距离 d 描述因此对于平面 n · p d 0 上的点 p [x, y, z]ᵀ。我们可以 将其写为 但请注意这是超定的 - 解空间平面是三维的但上面的描述使用了四个值。 因此让我们首先通过限制解决方案空间来删除一个组件。 我们通过任意指定 c 1 来实现这一点即平面法线的 z 分量始终为 1请注意法线的长度不需要为 1。 如果你认为这是一个潜在有问题的假设那么你是对的——我们稍后会再讨论这个问题。 现在让我们定义 并求解a、b、d。 矩阵形式 接下来我们将这个矩阵转置然后从左侧相乘以执行线性最小二乘 转置后相乘 其中 N 是点数。 现在这是聪明的部分让我们定义上面的 x,y,z 相对于点云的质心平均值。 现在 Σx Σy Σz 0 所以我们可以简化为 从最后一行N·d 0我们可以得出结论d 0。这意味着如果所有点都相对于点云的质心则平面穿过原点。 换句话说平面始终穿过输入点的平均值。 我们现在可以去掉一个维度 克莱默规则告诉我们 我们可以通过将 n 乘以 D 来简化它无论如何我们都需要对 n 进行归一化这给我们 就是这样 但请记住我们的假设平面法线的 z 分量不为零。 如果为零怎么办 那么可以证明上面的行列式 D 变为零并且我们可以除以零。 即使它不完全为零但很接近我们仍然会得到不好的条件从而得到不好的结果。 所以我们能做些什么 好吧如果这些点跨越一个平面则法线的至少一个分量必须非零。 因此让我们对三个单独的假设进行上述计算其中哪个分量不为零。 然后我们简单地选择表现最好的一个即具有最大行列式的那个。
注意此方法将最小化垂直于主轴的残差的平方而不是垂直于平面的残差的平方。 如果残差很小即你的点都靠近生成的平面那么这种方法可能就足够了。 但是如果你的点分布比较分散那么此方法可能不是最合适的。 这是 Rust 代码
// Constructs a plane from a collection of points
// so that the summed squared distance to all points is minimzized
fn plane_from_points(points: [Vec3]) - OptionPlane {if points.len() 3 {return None; // At least three points required}let mut sum Vec3{x:0.0, y:0.0, z:0.0};for p in points {sum p;}let centroid sum * (1.0 / (points.len() as f64));// Calc full 3x3 covariance matrix, excluding symmetries:let mut xx 0.0; let mut xy 0.0; let mut xz 0.0;let mut yy 0.0; let mut yz 0.0; let mut zz 0.0;for p in points {let r p - centroid;xx r.x * r.x;xy r.x * r.y;xz r.x * r.z;yy r.y * r.y;yz r.y * r.z;zz r.z * r.z;}let det_x yy*zz - yz*yz;let det_y xx*zz - xz*xz;let det_z xx*yy - xy*xy;let det_max max3(det_x, det_y, det_z);if det_max 0.0 {return None; // The points dont span a plane}// Pick path with best conditioning:let dir if det_max det_x {Vec3{x: det_x,y: xz*yz - xy*zz,z: xy*yz - xz*yy,}} else if det_max det_y {Vec3{x: xz*yz - xy*zz,y: det_y,z: xy*xz - yz*xx,}} else {Vec3{x: xy*yz - xz*yy,y: xy*xz - yz*xx,z: det_z,}};Some(plane_from_point_and_normal(centroid, normalize(dir)))
} 原文链接3D点云平面拟合 - BimAnt