【问题标题】:How to calculate the volume of a 3D mesh object the surface of which is made up triangles如何计算表面由三角形组成的 3D 网格对象的体积
【发布时间】:2009-09-10 15:34:05
【问题描述】:

我想计算一个表面由三角形组成的 3D 网格物体的体积。

【问题讨论】:

标签: math geometry volume


【解决方案1】:

Reading this paper,其实是一个很简单的计算。

诀窍是计算四面体的有符号体积 - 基于您的三角形并在原点处达到顶峰。体积的符号来自你的三角形是否指向原点的方向。 (三角形的法线本身取决于顶点的顺序,这就是为什么下面没有明确引用它的原因。)

这一切都归结为以下简单的功能:

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

【讨论】:

  • 相当优雅的解决方案。
  • 我想知道为什么这在 2001 年之前没有被发现。或者它是,但没有相关性?
  • 1984 年 10 月,发表了论文“一种计算任意非凸多面体积分性质的符号方法”,并描述了这种计算体积的方法。这或多或少也是一种微不足道的方法,因此发表论文需要的不仅仅是这些信息。
  • “在原点封顶”不是强制性的,您可以选择任何固定点。如果物体离原点很远,这将导致数值不稳定。最好从网格中选择任意点
  • 我根据相同的几何形状计算体积。首先,我从实体网格中获取体积。然后我提取表面并根据该算法计算体积。结果是不同的。前者为 16.46584046,后者为 16.46596493
【解决方案2】:

Yip Frank Kruegers 的回答对此效果很好 +1。如果您有可用的矢量函数,您也可以使用它:

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

edit .. 添加了 impl。如果您不确定,请使用 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
            );
        }
        ...
    }

【讨论】:

  • 也许是 Dot() AND Cross() 的邮政编码? (实现起来都很简单,但为了完整性)。顺便说一句,@Frank Kruegers 的答案就是简化 p1.Dot(p2.Cross(p3)) / 6.0f
【解决方案3】:

GNU Triangulated Surface Librarycan do this for you。请记住,曲面必须是封闭的。对于很多 3D 模型来说,情况并非如此。

如果你想自己实现它,你可以先看看他们的代码。

【讨论】:

  • 如果你重新实现它,请小心 - GTS 库是 LGPL,所以任何衍生作品都必须是 LGPL 或 GPL。
【解决方案4】:

上述方法适用于“简单”对象(没有相交/重叠的三角形),如球体四面体等。对于更复杂的形状,一个好主意是分割网格(关闭它)并分别计算每个部分的体积。 希望这会有所帮助。

【讨论】:

  • 如果卷已签名,则不需要中心在里面
  • 错误答案。所描述的方法对于没有相交/重叠三角形的任意复杂封闭对象是正确的,并且对中心点的位置没有要求。那是因为四面体“体积”是有符号的并以代数方式相加。
  • @galinette 是的,你是对的。 “简单”对象是指没有相交/重叠三角形的对象。网格的中心也可以在外面。
  • 用 3d 布尔运算切割它
猜你喜欢
  • 2014-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-09
  • 2022-01-27
  • 1970-01-01
  • 2022-10-30
  • 2023-03-24
相关资源
最近更新 更多