如何计算存储在STL文件中的物体的体积?

4

我有一些 .stl 文件(STL 是由 3D Systems 创建的用于立体光刻 CAD 软件的本地文件格式),我需要计算它们的体积。该如何做呢?我正在使用以下公式进行计算,但是得到的体积与其他软件计算出的不一致。

float x1,y1,z1;
float x2,y2,z2;
float x3,y3,z3;

上面是顶点。triangles只是一个数据结构,它保存了每个三角形的顶点对象。
totalVolume += currentVolume = 
(triangles[i].x1*triangles[i].y2*triangles[i].z3 - 
triangles[i].x1*triangles[i].y3*triangles[i].z2 -

triangles[i].x2*triangles[i].y1*triangles[i].z3 + 
triangles[i].x2*triangles[i].y3*triangles[i].z1 + 
triangles[i].x3*triangles[i].y1*triangles[i].z2 - 
triangles[i].x3*triangles[i].y2*triangles[i].z1) / 6;

你是否也涉及使用法向量进行计算?


1
什么是 .stl 文件?另一种软件是什么?还有,什么是 plizz?! - Björn Pollex
http://en.wikipedia.org/wiki/STL_%28file_format%29 请帮忙翻译,谢谢。 - Dominic Chibamu
请解释一下.stl文件是什么,并告诉我们您使用的软件。 - pavium
STL是由3D Systems创建的立体光刻CAD软件本地支持的文件格式。 - Dominic Chibamu
2
@pavium:这个问题被标记为CAD问题。熟悉CAD的人应该对.stl文件很熟悉。 - Codie CodeMonkey
显示剩余5条评论
2个回答

6
在维基百科的多面体文章中讨论了多面体的容积。任何有效的STL镶嵌必须精确地是一个多面体,其中每个平面都是一个边,因此在那里讨论的公式成立。
假设顶点按逆时针方向定向(朝向外表面法线),则以下扩展成立: Expanding in terms of the triangle vertices 方程式1只是多面体的发散公式。p[i,j]是第i个三角形的第j个顶点(作为从原点的矢量)。
方程式2通过使用两个三角形侧面(平行四边形)的叉积是三角形的法向量,并且大小是三角形面积的两倍这一事实进行扩展。
顺便说一下,这就是为什么三角形法线不会出现在您的表达式中,尽管您的直觉认为它应该以某种方式存在。它已经在其中了!
方程式3只是使用叉积的分配属性以及矢量叉积本身是零矢量的事实来扩展方程式2。
从方程式3得到的体积根据三角形的方向进行标记。我已经调整了我的公式以与您的代码一致,但是您可能会得到一个负结果。如果是这样,请取绝对值。
现在按照您的符号(除了我不把重复的三角形[i]放进去)编写总和项:
(-x3 y2 z1 + x2 y3 z1 + x3 y1 z2 - x1 y3 z2 - x2 y1 z3 + x1 y2 z3)/6.;

这与您所写的完全匹配(除了顺序)!

因此有几种可能:

(1) 可能您的STL文件存在缺陷,三角形没有一致地定向。您可以通过验证每个边缘在正向上被一个三角形使用一次,在相反方向上使用一次来检查这一点。我更改了符号并使用下标表示文件中唯一索引的顶点,而不是像上面使用两个索引符号那样表示相对于面的顶点索引。

如果三角形的边缘(p[r], p[s])在其定向边缘列表中,则其他三角形必须具有(p[s], p[r])(相同的顶点,反转的顺序)在其定向边缘列表中。

(2) 剖分没有封闭。这与1相同的测试,只是当仅有一个三角形使用该边时,无论朝向如何,它都是开放的。

(3) 我敢提一下吗?您确定已经初始化了currentVolume吗?

(4) 您得到了正确的答案,但体积为负数,您被欺骗以为方法是错误的。请参见我上面的评论。


非常感谢DeepYellow,现在我完全明白如何获取它。如果我想从stl文件中获取物体的长度、宽度和高度,那么获取X轴范围等于长度,获取Y轴范围等于宽度,获取Z轴范围等于高度,是这样吗?这里的长度、宽度和高度是指包含矩形立方体的尺寸。 - user726899
是的,查看x、y和z坐标的范围将为您提供镶嵌体的边界框尺寸。 - Codie CodeMonkey
如果您应用四面体体积的总和来得出一个答案,然后移动原点并重新进行求和,您是否会得到不同的答案?如果是这样,那么您的多面体可能是开放的。 - emsr
方程式3中的最后两项将消失,因为每个叉积必须正交于p_i,1。因此,当您的p_i,1与叉积的点积应该消失时。 - emsr

1

int和double的问题?

/ 6; 可能应该是 / 6.0;


你可能想在这个答案上再多解释一些。 - Caribou

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接