计算封闭三角网格多面体的有向体积:将关于原点的四面体体积代数相加,面外法向为正,结果为 v/6。
Description: Magic formula for the volume of a polyhedron. Faces should point outwards. Status: tested
展开阐述
-
定义与背景
- 场景:给定由三角面片组成的封闭多面体网格(每个面以顶点索引 a,b,c 表示),需快速求体积。
- 有向体积:采用右手系,面片顶点顺序按外法向(朝外)排列时,为正体积;若顺序颠倒(法向朝内)则贡献为负。
- 表达:将多面体拆为“原点 O 与面片三角形 △(p[a],p[b],p[c])”构成的若干四面体;代数和即体积(与散度定理一致)。
-
接口/数据结构(据实现)
- 函数签名:template<class V, class L> double signedPolyVolume(const V& p, const L& trilist)
- p:顶点数组(例如 vector<Point3D
> 或等价的三维向量类型) - trilist:三角面列表(元素含 a,b,c 顶点索引)
- 返回值:有向体积(朝外为正)
- p:顶点数组(例如 vector<Point3D
- 几何量与单位:坐标单位为“长度”,叉积·点积组合得到“长度^3”,最终体积单位与输入一致。
- 函数签名:template<class V, class L> double signedPolyVolume(const V& p, const L& trilist)
-
核心流程/要点
- 面分解与符号一致性
- 对每个三角面 (a,b,c) 计算 S = (p[a]×p[b])·p[c]
- 代数和 v = Σ S,体积 = v / 6
- 直觉:混合积 u·(v×w) 即以 u,v,w 构成平行六面体的有向体积;三角面与原点的四面体体积为该混合积的 1/6
- 参考点与开口性
- 以“原点”为参考的四面体分解;只要网格封闭且面朝外,结果与原点位置无关(代数和会相互抵消平移影响)
- 若网格不闭合或法向不一致,将导致体积估计错误(出现泄漏或部分负贡献)
- 法向方向的校验
- 面顶点顺序应满足外法向;若来源不保证,可用点-面关系或多面体重心处于“内侧”的规则统一方向
- 在 040-几何-三维点 中,叉积方向由右手定则决定;应全局保持一致的右手系
- 退化与稳健性
- 退化面(共线/零面积)贡献为 0,不影响体积
- 顶点非常接近原点或坐标量级很大时,浮点舍入误差会累积;可选 long double 提升稳健性
- 若坐标使用整数且数值范围大,混合积中间量可能超出 64 位范围,需以 128 位整型或长浮点过渡
- 面分解与符号一致性
-
复杂度与边界条件
- 时间:O(F),F 为三角面数;一次线性遍历
- 边界:
- 开放网格/自交网格:不在定义域内(体积不确定);自交会产生代数体积与“几何填充体积”不一致
- 面向内:体积取负;混合存在内外不一致时,最终数值会被抵消或失真
- 顶点在原点附近:公式有效;原点无需在体内
- 数值与溢出:
- 三重积涉及“乘乘加”,建议对大坐标采用 long double 或 128 位整型中间值
- 批量累计时注意使用 Kahan 或 pair-sum 等技巧可进一步降低浮点损失(可选)
-
变体/扩展
- 参考点换元:亦可选用任意参考点 O0,把 p[i] 替换为 p[i]−O0;若网格闭合且朝外,和不变
- 非三角面网格:每个多边形面先三角化(保持方向一致),再套用同一公式
- 凸/非凸多面体:公式均适用;非凸情形的凹陷会通过负贡献正确抵消
- 与重心计算协同:与043-几何-多边形重心的“面积×质心”思想类似,3D 可通过对四面体“体积×质心”求加权平均得到整体质心(实现不在本节点)
-
正确性要点与不变式
- 向量恒等式:混合积的循环置换不变与符号性质确保“面方向一致 ⇔ 体积符号一致”
- 保守性:对封闭曲面的通量积分(散度定理)与四面体分解一致,线性累加不重不漏
- 方向不变式:统一外法向后,任何局部面顺序变换都会被全局一致性吸收,保持体积正确
-
与相邻技术的对比与取舍
- 与体素/栅格近似:本法为解析精确解;体素化适合近似体积或布尔运算的数值方法
- 与三维凸包 017-几何-三维凸包:若仅有点集需体积,可先构造凸包并以其三角面应用本公式
- 与二维面积 042-几何-多边形面积 的鞋带公式:三维体积等价于“3D 鞋带”的混合积版本