3Dボリュームと2D平面の間の交差領域を計算する方法


8

こんにちは、誰かが私の問題を解決する方法についての洞察を提供してくれるなら素晴らしいです!

3Dボリュームと2D平面の間の交差領域を計算しようとしています。3Dボリューム:6点で定義(常に太い三角形に似た3Dウェッジになります)2D平面:3点で定義

助言がありますか?このタスクを実行できるオープンソースソフトウェアはありますか?

どうもありがとうクリス

回答:


5

この質問に対する特効薬の答えはありません。ある時点で、それを吸い取ってすべてのケースを検討する必要があります。私はかつて三角形と円の交点を計算しなければならなかった...それはひどかった。3D形状には一定の対称性があるため(常に三角プリズムであるという事実など)、可能性を大幅に絞り込むことができます。

  1. 各点が平面のどちら側にあるかを見つけます。
  2. すべてのポイントが片側にある場合は、完了です。
  3. 1つの点が平面によって他の5つから分離されている場合、交差は三角形です。おそらく、どの面が頂点に入射しているかを示す接続情報があり、平面と平面の交差による3つの線を計算してから、交差の三角形を計算できます。これはすべて、交差する平面のパラメーター化で行うのが最善です。
  4. 2つの点が分離されています。どちらもプリズムの同じ三角形の面にあるか、反対の三角形の面にある2つの対応する点にあります。どちらの場合も、交差は四辺形です。
  5. 3点の場合、それらはすべて同じ三角形の面またはその上の2つだけの面になります。ここでは、結果として生じる三角形または六角形の2つのケースがあります。

これらは実際に唯一の高レベルのケースであり、適用する必要のある対称性の削減が明らかにあります(ケース5では、1ポイントのケースは他の三角形のファセットの2ポイントのケースと同等です)。

あなたへの私の1つの提案は、形状の堅牢な表現を選択し、堅牢な述語を使用して幾何学的テストを実行することです。平面の場合、それは平面上の点と単位法線ベクトルとして最もよく表されます。プリズムは、1つの軸がプリズムの押し出し方向に位置合わせされた正規直交基底(トライアド)を定義することによって表されます。1つの頂点を原点に置き、三角形の面の他の2つをトライアドのuv座標で表すと、高さとベース頂点のグローバルオフセットを格納するだけで済みます。基本的に、私は考えています

struct plane{
    double p[3]; // point on plane
    double n[3]; // unit normal vector to plane
};
struct TriPrism{
    double basis[9]; // 3x3 orthogonal matrix of local coordinate frame (det = +1)
    // Stored columnwise, first two vectors are in the plane of the triangular face)
    // Last vector is parallel to extrusion direction, call the set [u, v, w]
    double base[3]; // global coordinates of base vertex (where the basis vectors are "rooted")
    double buv[2]; // the uv-coordinates of the second point on the triangular face
    double cuv[2]; // third point on triangular face
    // Assume that the "bottom" triangular face is formed by vertices (a,b,c)
    // with base being a, and (b-a) cross (c-a) directed along vector w (instead of against)
    double h; // height of prism ("top" triangular face is h*w offset from the "bottom" face)
};

この表現は、プリズムを動かすのにロバストであり、最も病理的な場合を除いて、すべての場合に高い相対精度を維持する必要があります。

堅牢な述語については、 通常の浮動小数点数を使用することを想定して、Shewchukの堅牢な述語を強くお勧めします。主に使用しますorient3d

最終的な出力ポリゴンの表現に関しては、平面の適切なパラメーター化を選択します。私の意見では、最良の選択は、平面の法線ベクトルでGram-Schmidtによって決定される平面の正規直交基底セットを最初に選択することです(ここのgeom_maketriad3dを参照)。次に、その2Dパラメトリック平面の原点を、平面へのプリズム基点の投影とします。これにより、結果のポリゴンが配置される場所の近くにパラメーター化が実際に適用され、関連する浮動小数点数のビットを効果的に使用できるようになります。可能であれば、このパラメーター化を使用して残りのすべての計算を実行します。

一般に、これらのばかげた数値の考慮により、幾何学的計算には危険が伴います(上記の5の場合、平面近くの頂点でのわずかなエラーにより、結果が4ゴンから6ゴンに劇的に変わる可能性があります)。一度にいくつかのケースを処理し、結果を視覚化することをお勧めします。ここには、ポストスクリプトのような入力言語機能を備えた、かなりシンプルなビューアプログラムがあります。プリズムのファセットをダンプして平面を描画し、結果のポリゴンも描画して、それらが正しいかどうかを視覚的に確認できます。

補遺:もともと交差ポリゴンの領域が必要であることを忘れていました。取るに足らないことですが、分からない場合は、カットプレーンのポリゴンのエッジを定義するラインのコレクションを取得したら、それを頂点表現に変換する必要があります。ファセット平面と平面の交差から交差を作成したので、ラインの順序、つまりポリゴンの周りを移動するエッジの順序を追跡できているはずです。頂点を取得するには、これらの線の連続するペアの交差を計算するだけです。頂点を取得したら、面積を取得するのは簡単です(例:geom_polygon_area2dを参照)。完全にカットプレーンのUV座標で作業した場合は、それらを直接そのような関数に供給して面積を取得できます。

さらに、カットプレーンの適切な大きな領域を選択し、ポイントをランダムにサンプリングして、それらがプリズム内にあるかどうかを確認する(これは凸型であるため安価です)という明白な方法があります。次に、面積を、合計ポイントに対する内部ポイントの比率として、サンプリング領域の面積を掛けて計算できます。精度を本当に気にしない場合、これはおそらくより高速になりますが、それ以外の場合は、その組み合わせの複雑さにもかかわらず、分析メソッドがそれほど遅くなることはありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.