How to calculate the volume of a 3D mesh object the surface of which is made up triangles

MathGeometryVolume

Math Problem Overview


I want to calculate the volume of a 3D mesh object having a surface made up triangles.

Math Solutions


Solution 1 - Math

Reading this paper, it is actually a pretty simple calculation.

The trick is to calculate the signed volume of a tetrahedron - based on your triangle and topped off at the origin. The sign of the volume comes from whether your triangle is pointing in the direction of the origin. (The normal of the triangle is itself dependent upon the order of your vertices, which is why you don't see it explicitly referenced below.)

This all boils down to the following simple function:

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

and then a driver to calculate the volume of the mesh:

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

Solution 2 - Math

Yip Frank Kruegers answer works well +1 for that. If you have vector functions available to you you could use this too:

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

edit .. added impl. for Dot() and Cross() if you are unsure. Most Math libs will have these. If you are using WPF they are implemented as static methods of the Vector3D class.

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

Solution 3 - Math

The GNU Triangulated Surface Library can do this for you. Keep in mind that the surface must be closed. That is not going to be the case for quite a few 3D models.

If you want to implement it yourself, you could start by taking a look at their code.

Solution 4 - Math

The method above is correct for "simple" objects (no intersecting/overlapping triangles) like spheres tetrahedras and so on. For more complex shapes, a good idea could be to segment the mesh (close it) and calculate the volume of each segment separately. Hope this helps.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionCan SariView Question on Stackoverflow
Solution 1 - MathFrank KruegerView Answer on Stackoverflow
Solution 2 - MathRoss OliverView Answer on Stackoverflow
Solution 3 - MathJay KominekView Answer on Stackoverflow
Solution 4 - MathAnoroahView Answer on Stackoverflow