web-dev-qa-db-fra.com

Comment calculer le volume d'un objet maillé 3D dont la surface est constituée de triangles

Je veux calculer le volume d'un objet maillé 3D ayant une surface composée de triangles.

46
Can Sari

En lisant cet article , il s'agit en fait d'un calcul assez simple.

L'astuce consiste à calculer le volume signé d'un tétraèdre - basé sur votre triangle et complété à l'origine. Le signe du volume vient du fait que votre triangle pointe dans la direction de l'origine. (La normale du triangle dépend elle-même de l'ordre de vos sommets, c'est pourquoi vous ne le voyez pas explicitement référencé ci-dessous.)

Tout cela se résume à la fonction simple suivante:

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);
}

puis un driver pour calculer le volume du maillage:

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

La réponse de Yip Frank Kruegers fonctionne bien +1 pour cela. Si vous disposez de fonctions vectorielles, vous pouvez également l'utiliser:

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

modifier .. ajout impl. pour Dot () et Cross () si vous n'êtes pas sûr. La plupart des bibliothèques Math en auront. Si vous utilisez WPF, elles sont implémentées en tant que méthodes statiques de la classe 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 Librarypeut le faire pour vous . Gardez à l'esprit que la surface doit être fermée. Ce ne sera pas le cas pour pas mal de modèles 3D.

Si vous voulez l'implémenter vous-même, vous pouvez commencer par jeter un œil à leur code.

4
Jay Kominek

La méthode ci-dessus est correcte pour les objets "simples" (pas de triangles se croisant/se chevauchant) comme les sphères tétraèdres, etc. Pour les formes plus complexes, une bonne idée pourrait être de segmenter le maillage (le fermer) et de calculer le volume de chaque segment séparément. J'espère que cela t'aides.

0
Anoroah