Как рассчитать объем трехмерного сетчатого объекта, поверхность которого состоит из треугольников - PullRequest
44 голосов
/ 10 сентября 2009

Я хочу рассчитать объем трехмерного объекта сетки, поверхность которого состоит из треугольников.

Ответы [ 4 ]

76 голосов
/ 14 октября 2009

Читая эту статью , на самом деле это довольно простой расчет.

Хитрость заключается в том, чтобы вычислить подписанный объем тетраэдра - на основе вашего треугольника и завершенного в начале координат Знак объема зависит от того, указывает ли ваш треугольник в направлении начала координат. (Нормаль треугольника сама по себе зависит от порядка ваших вершин, поэтому вы не видите на него явную ссылку ниже.)

Все это сводится к следующей простой функции:

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());
}
19 голосов
/ 18 декабря 2012

Ип Фрэнк Крюгерс ответ хорошо работает +1 за это. Если у вас есть векторные функции, вы можете использовать это тоже:

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

изменить .. добавлено вкл. для Dot () и Cross (), если вы не уверены. У большинства математиков будут такие. Если вы используете 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
            );
        }
        ...
    }
4 голосов
/ 10 сентября 2009

Библиотека GNU Triangulated Surface * может сделать это для вас . Имейте в виду, что поверхность должна быть закрыта. Это не будет иметь место для многих 3D моделей.

Если вы хотите реализовать это самостоятельно, вы можете начать с просмотра их кода.

0 голосов
/ 24 апреля 2015

Приведенный выше метод подходит для «простых» объектов (без пересекающихся / перекрывающихся треугольников), таких как сферы, тетраэдры и так далее. Для более сложных форм хорошей идеей может быть сегментирование сетки (ее закрытие) и вычисление объема каждого сегмента отдельно. Надеюсь, это поможет.

...