2

平面を 3D 空間の一連の点に合わせようとしています。最初に徹底的な最小二乗法を試みましたが、これは遅すぎることが判明しました。最も効率的な解決策は、特異値分解を実行することだと読みました。

これの計算は私にはできませんが、これを機能させるためのリソースがたくさん見つかりました。

この投稿の回答によると、ポイントの重心を計算し、すべてのポイントから重心を減算し、それらを 3xN 行列に入れ、SVD を実行する必要があります。次に、左特異ベクトルを平面の法線として使用します。

ここまでは順調ですね。

SVD 用の機能を持つ alglib という C# 数学ライブラリを見つけました。アルゴリズムの定義はここにあります。これは、データ ポイント マトリックスに加えて入力としてさらに 2 つのマトリックスが必要なため、問題が発生している場所であり、それらの中に何を入れればよいかよくわかりません。私は関係なくこのコードを実行しました:

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 については、こちらを参照してください。

この問題に関する知識を共有できる数学またはアルゴリズムのベテランはいますか? プロジェクトが Unity3D にあるため、C# を使用する必要があります。必要に応じて、さらに情報を提供させていただきます。

4

1 に答える 1

2

ドキュメントを見ると、w には特異値が含まれ、U には左特異ベクトルが含まれ、V には右特異ベクトルが含まれるように見えます。dataMat は 3xN であるため、U は 3x3、V は NxN である必要があります。そして、左特異ベクトルが必要だと言うように、UNeeded=1 を設定し、U の最初の列を取得します。右特異ベクトルは必要ないため、VNeeded=0 を設定することもできます。

于 2015-03-30T21:34:11.460 に答える