给定顶点列表(v
),连接顶点(e
)的边列表以及连接边(s
)的曲面列表,如何计算多面体的体积?
答案 0 :(得分:8)
注意:
[x1 x2 x3 x4]
[y1 y2 y3 y4]
[z1 z2 z3 z4]
[1 1 1 1]
其中列是verticies(x,y,z,1)的齐次坐标。
即使形状没有通过减去该体积以及添加它来封闭原点,它仍然有效,但这取决于具有一致的排序。
如果你不能保留顺序,你仍然可以找到一些方法将其分解为四面体,并将每个行列式的行列式的1/6绝对值加起来。
答案 1 :(得分:2)
与多边形类似,我们可以将其分成三角形并对区域求和,
你可以将一个多面体分成金字塔并将它们的体积相加。但我不确定为此实现算法有多难。
(我相信有一种数学方法/公式,比如使用向量和矩阵 我建议您在http://mathoverflow.net)
上发布您的问题答案 2 :(得分:1)
首先,通过绘制新边缘将每个面分成三角形。
现在看一个三角形,并假设它位于“上”表面(其中一些细节将在以后变得不重要)。查看三角形下方的体积,下至多面体下方的某个水平面。如果{h1,h2,h3}是三个点的高度,并且A是基部的面积,那么实体的体积将是A(h1 + h2 + h3)/ 3。现在我们必须为上面添加这些实体的体积,并为下面减去它们以获得多面体的体积。
与代数一起玩,你会发现多面体在水平面上方的高度无关紧要。平面可以在多面体上方,或通过它,结果仍然是正确的。
所以我们需要的是(1)计算基础面积的方法,以及(2)从“较低”面部告诉“上”面的方法。第一个很容易,如果你有点的笛卡尔坐标,第二个很容易,如果点是有序的,你可以结合它们,一石二鸟。假设每个面都有逆时针顺序的角点列表。然后,这些点在x-y平面上的投影对于上表面是逆时针方向,对于下表面是顺时针方向。如果你使用this method来计算基础面积,那么它对于一个上面会呈现正面,而对于一个上面则会为负,所以你可以将它们全部加在一起并得到答案。
那你怎么得到有序的角落列表?从一个三角形开始,选择一个排序,对于每个边缘,共享该边缘的邻居应该以相反的顺序列出这两个点。从邻居移动到邻居,直到每个三角形都有一个列表。如果多面体的体积变为负数,则只需乘以-1(这意味着您为第一个三角形选择了错误的顺序,并且多面体是由内到外的。)
修改: 我忘记了最好的部分!如果你检查代数是否要添加这些卷,你会看到许多术语被取消,特别是在将三角形组合回原始面时。我没有详细说明这一点,但看起来最终的结果可能是一个非常简单的功能。
答案 3 :(得分:1)
我以前做过这个,但我使用的表面网格总是有三角形面。如果网格具有非三角形刻面,则可以先将它们轻松分解为三角形刻面。然后我把它喂给TetGen以获得内部的四面体化。最后,我把四面体的所有卷都加起来了。 TetGen相当容易使用,并且是除CGAL之外唯一可以处理复杂网格的库。如果你不介意安装一个巨大的库并使用疯狂的模板,CGAL很容易使用。
答案 4 :(得分:0)
这是Python中的潜在实现。 任何人都可以检查一下是否正确? 我相信我错过了积分的排列,因为我的第二个测试(立方体)给出0.666而不是1.想法有人吗?
干杯 EL
class Simplex(object):
'''
Simplex
'''
def __init__(self,coordinates):
'''
Constructor
'''
if not len(coordinates) == 4:
raise RuntimeError('You must provide only 4 coordinates!')
self.coordinates = coordinates
def volume(self):
'''
volume: Return volume of simplex. Formula from http://de.wikipedia.org/wiki/Tetraeder
'''
import numpy
vA = numpy.array(self.coordinates[1]) - numpy.array(self.coordinates[0])
vB = numpy.array(self.coordinates[2]) - numpy.array(self.coordinates[0])
vC = numpy.array(self.coordinates[3]) - numpy.array(self.coordinates[0])
return numpy.abs(numpy.dot(numpy.cross(vA,vB),vC)) / 6.0
class Polyeder(object):
def __init__(self,coordinates):
'''
Constructor
'''
if len(coordinates) < 4:
raise RuntimeError('You must provide at least 4 coordinates!')
self.coordinates = coordinates
def volume(self):
pivotCoordinate = self.coordinates[0]
volumeSum = 0
for i in xrange(1,len(self.coordinates)-3):
newCoordinates = [pivotCoordinate]
for j in xrange(i,i+3):
newCoordinates.append(self.coordinates[j])
simplex = Simplex(newCoordinates)
volumeSum += simplex.volume()
return volumeSum
coords = []
coords.append([0,0,0])
coords.append([1,0,0])
coords.append([0,1,0])
coords.append([0,0,1])
s = Simplex(coords)
print s.volume()
coords.append([0,1,1])
coords.append([1,0,1])
coords.append([1,1,0])
coords.append([1,1,1])
p = Polyeder(coords)
print p.volume()