一种从.stl(立体光刻)文件计算质心的方法?

Fak*_*ken 7 c++ theory 3d

我试图计算STL文件中定义的对象的质心(x,y,z)坐标(立体光刻,不要与标准模板库混淆).STL文件包含由三角形边界定义的闭合对象(或多个对象).三角形本身不一定是任何顺序,文件只是浮动在3D空间中的每个三角形的坐标3个顶点加上三角形的法线向量(法线应该被忽略,因为它并不总是正确地完成).没有任何东西可以将每个三角形相互链接,假设对象已关闭.

一种简单的方法是将体积(在本例中为一个盒子)分成数百万个元素,并确定每个元素是否在STL文件中定义的对象内,然后总结时刻并计算质心.这可行,但它远非优雅和极慢.

另一种方法是将边界表示转换为多个填充的四面体实体.形成我可以计算每个四面体的质心,其体积和产生的力矩,从而根据所有四面体的总和计算总质心.这个问题是我不知道如何将三角形的曲面表示转换为四面体的体积表示(我假设它是一个相当不重要的任务).

任何人都知道任何方法,或者可以想到我可以尝试的任何方法?或者甚至可能是任何谈论这个的参考资料?

有关STL文件的更多信息(前两个部分很重要,其他一切都没用):http://en.wikipedia.org/wiki/STL_%28file_format%29

Fak*_*ken 12

经过大量的思考和实验,我得到了答案!

首先,我们为每个三角形添加第4个点,使它们成为具有体积质心的四面体.我们计算质量的体积和中心,并将它们相互乘以得到我们的时刻.我们总结时刻并除以总体积来得到我们的整体质心.

我们使用此处显示的确定方法计算体积(公式32):http://mathworld.wolfram.com/Tetrahedron.html

每个四面体的质心仅仅是4个点的平均值.

这里的技巧是,由于创建STL文件的方式,三角形具有从零件表面向外指向的法线,遵循用于创建三角形的3个顶点的右手规则.我们可以通过允许我们使用一致的约定来确定是否应该从我们的网络部分添加或减去四面体的体积(这是因为我们选择的参考点可能不一定在部分内部)并且整个部分不一定是凸的,而是一个封闭的物体).

使用确定方法计算体积,前三个坐标点将代表三角形的三个点.第四点是我们的共同起源.如果由三角形创建的法线(遵循右手规则从点1,2,3开始)指向我们的公共参考点,则该体积将被计算为不是我们整体实体或负体积的一部分(通过指向,我的意思是由三角形法线创建的矢量松散地指向与从我们的参考点到四面体的质心的矢量创建的法线平面相同的一侧.如果矢量指向远离参考点,则它是正体积或在部件内部.如果是正常的,则由于三角形与参考点位于同一平面,因此体积变为零.

我们不需要担心实际跟踪任何这些,就好像我们的输入一致(如三角形遵循右手规则,正常面向外部),确定将给我们正确的符号.

无论如何,继承人的代码(它比解释更简单).

class data // 3 vertices of each triangle
{
public:
    float x1,y1,z1;
    float x2,y2,z2;
    float x3,y3,z3;
};

int main ()
{
    int numTriangles; // pull in the STL file and determine number of triangles
    data * triangles = new triangles [numTriangles];
    // fill the triangles array with the data in the STL file

    double totalVolume = 0, currentVolume;
    double xCenter = 0, yCenter = 0, zCenter = 0;

    for (int i = 0; i < numTriangles; i++)
    {
        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;
        xCenter += ((triangles[i].x1 + triangles[i].x2 + triangles[i].x3) / 4) * currentVolume;
        yCenter += ((triangles[i].y1 + triangles[i].y2 + triangles[i].y3) / 4) * currentVolume;
        zCenter += ((triangles[i].z1 + triangles[i].z2 + triangles[i].z3) / 4) * currentVolume;
    }

    cout << endl << "Total Volume = " << totalVolume << endl;
    cout << endl << "X center = " << xCenter/totalVolume << endl;
    cout << endl << "Y center = " << yCenter/totalVolume << endl;
    cout << endl << "Z center = " << zCenter/totalVolume << endl;
}
Run Code Online (Sandbox Code Playgroud)

计算STL文件的质心非常快.

  • 我已经对CAD程序(SolidWorks)的结果进行了非常仔细的测试,结果在千分之一毫米之内.这里的技巧是大部分算法都被简化了,因为我选择了原点(0,0,0)作为第4个顶点.这消除了问题复杂性的绝大部分,因此你最终得到的东西看起来像是处理表面(因为你只看到3点,第4点取消了与之相关的所有内容,因为它为零). (2认同)