三角形で構成された表面を持つ3Dメッシュオブジェクトの体積を計算したい。
このペーパーを読む 、実際には非常に単純な計算です。
トリックは、四面体の署名されたボリュームを計算することです-三角形に基づいて、原点で終了します。ボリュームのサインは、三角形が原点の方向を指しているかどうかに基づいています。 (三角形の法線自体は頂点の順序に依存しているため、以下で明示的に参照されているのは表示されません。)
これらはすべて、次の単純な関数に要約されます。
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());
}
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
);
}
...
}
GNU Triangulated Surface Libraryこれを行うことができます 。表面を閉じる必要があることに注意してください。これは、かなりの数の3Dモデルには当てはまりません。
自分で実装したい場合は、まずそのコードを見てみましょう。
上記の方法は、球体の四面体などの「単純な」オブジェクト(交差/重複する三角形がない)に適しています。より複雑な形状の場合、メッシュをセグメント化して(閉じる)、各セグメントのボリュームを個別に計算することをお勧めします。お役に立てれば。