我正在尝试将平面拟合到 3D 空间中的一组点。我最初尝试了详尽的最小二乘拟合,但结果太慢了。我读到最有效的解决方案是执行奇异值分解。
这个数学超出了我的范围,但我找到了一堆资源来尝试让它工作。
根据这篇文章的答案,我需要计算点的质心,从所有点中减去质心,将它们放入 3xN 矩阵并执行 SVD。然后我将左奇异向量作为平面的法线。
到目前为止,一切都很好。
我找到了一个名为 alglib 的 C# 数学库,它具有 SVD 的功能。该算法的定义可以在这里找到。这就是我遇到问题的地方,因为除了数据点矩阵之外,它还需要两个矩阵作为输入,而且我真的不明白要在其中放入什么。不管怎样,我都运行了这段代码:
Vector3 centroid = getCentroid(planeVerts);
double[,] dataMat = substractCentroid(planeVerts, centroid);
double[] w = new double[3];
double[,] u = new double[1,1];
double[,] t = new double[1, 1];
bool a = alglib.svd.rmatrixsvd(dataMat, 3, planeVerts.Length, 0, 0, 2, ref w, ref u, ref t);
Vector3 planeNorm = new Vector3((float) w[0], (float) w[1], (float) w[2]);
所以理论上我认为“w”会包含我的平面法线,但不幸的是它没有(我在 Unity3D 中可视化它并且它的角度错误)。“u”和“t”矩阵让我感到困惑,我真的不知道应该将它们设置为什么。
rmatrixsvd 函数的详细 API 可以在这里找到。
有没有数学或算法老手可以分享他们在这方面的知识?我需要使用 C#,因为我的项目在 Unity3D 中。如果需要,我很乐意提供更多信息。