web-dev-qa-db-ja.com

表面が三角形で構成されている3Dメッシュオブジェクトの体積を計算する方法

三角形で構成された表面を持つ3Dメッシュオブジェクトの体積を計算したい。

46
Can Sari

このペーパーを読む 、実際には非常に単純な計算です。

トリックは、四面体の署名されたボリュームを計算することです-三角形に基づいて、原点で終了します。ボリュームのサインは、三角形が原点の方向を指しているかどうかに基づいています。 (三角形の法線自体は頂点の順序に依存しているため、以下で明示的に参照されているのは表示されません。)

これらはすべて、次の単純な関数に要約されます。

public float SignedVolumeOfTriangle(Vector p1, Vector p2, Vector p3) {
    var v321 = p3.X*p2.Y*p1.Z;
    var v231 = p2.X*p3.Y*p1.Z;
    var v312 = p3.X*p1.Y*p2.Z;
    var v132 = p1.X*p3.Y*p2.Z;
    var v213 = p2.X*p1.Y*p3.Z;
    var v123 = p1.X*p2.Y*p3.Z;
    return (1.0f/6.0f)*(-v321 + v231 + v312 - v132 - v213 + v123);
}

次に、メッシュのボリュームを計算するドライバー:

public float VolumeOfMesh(Mesh mesh) {
    var vols = from t in mesh.Triangles
               select SignedVolumeOfTriangle(t.P1, t.P2, t.P3);
    return Math.Abs(vols.Sum());
}
79
Frank Krueger

Yip Frank Kruegersの回答は、+ 1でうまく機能します。ベクトル関数を使用できる場合は、これも使用できます。

    public static float SignedVolumeOfTriangle(Vector p1, Vector p2, Vector p3)
    {
        return p1.Dot(p2.Cross(p3)) / 6.0f;
    }

編集..実装を追加しました。不明な場合はDot()およびCross()を使用します。ほとんどのMathライブラリにはこれらがあります。 WPFを使用している場合、Vector3Dクラスの静的メソッドとして実装されます。

    public class Vector
    {
        ... 

        public float Dot(Vector a)
        {
            return this.X * a.X + this.Y * a.Y + this.Z * a.Z;
        }

        public Vector Cross(Vector a)
        {
            return new Vector(
              this.Y * a.Z - this.Z * a.Y,
              this.Z * a.X - this.X * a.Z,
              this.X * a.Y - this.Y * a.X
            );
        }
        ...
    }
20
Ross Oliver

GNU Triangulated Surface Libraryこれを行うことができます 。表面を閉じる必要があることに注意してください。これは、かなりの数の3Dモデルには当てはまりません。

自分で実装したい場合は、まずそのコードを見てみましょう。

4
Jay Kominek

上記の方法は、球体の四面体などの「単純な」オブジェクト(交差/重複する三角形がない)に適しています。より複雑な形状の場合、メッシュをセグメント化して(閉じる)、各セグメントのボリュームを個別に計算することをお勧めします。お役に立てれば。

0
Anoroah