凸多面体的质心

我有一个封闭的凸多面体,它是由一个凸多边形(面)arrays定义的,这些多边形由三维空间中的顶点数组定义。 假设密度均匀,我试图找到多面体的质心。 目前我用这个伪代码中的算法计算它。

public Vector3 getCentroid() { Vector3 centroid = (0, 0, 0); for (face in faces) { Vector3 point = face.centroid; point.multiply(face.area()); centroid.add(point); } centroid.divide(faces.size()); return centroid; } 

这基本上取面的质心的加权平均值。 我不是100%确定这是正确的,因为我无法在线找到正确的算法。 如果有人可以确认我的算法或引用我正确的算法我会很感激。

谢谢。


[编辑]

所以这是我用来查找质心的实际Java代码。 它将多面体分解为会聚在多面体内任意点上的金字塔。 金字塔质心的加权平均值基于以下公式。

C all = SUM 所有金字塔 (C 金字塔 *体积金字塔 )/体积全部

这是(评论很多的代码):

  // Compute the average of the facial centroids. // This gives an arbitrary point inside the polyhedron. Vector3 avgPoint = new Vector3(0, 0, 0); for (int i = 0; i < faces.size(); i++) { avgPoint.add(faces.get(i).centroid); } avgPoint.divide(faces.size()); // Initialise the centroid and the volume. centroid = new Vector3(0, 0, 0); volume = 0; // Loop through each face. for (int i = 0; i < faces.size(); i++) { Face face = faces.get(i); // Find a vector from avgPoint to the centroid of the face. Vector3 avgToCentroid = face.centroid.clone(); avgToCentroid.sub(avgPoint); // Gives the unsigned minimum distance between the face and a parallel plane on avgPoint. float distance = avgToCentroid.scalarProjection(face.getNormal()); // Finds the volume of the pyramid using V = 1/3 * B * h // where: B = area of the pyramid base. // h = pyramid height. float pyramidVolume = face.getArea() * distance / 3; // Centroid of a pyramid is 1/4 of the height up from the base. // Using 3/4 here because vector is travelling 'down' the pyramid. avgToCentroid.multiply(0.75f); avgToCentroid.add(avgPoint); // avgToCentroid is now the centroid of the pyramid. // Weight it by the volume of the pyramid. avgToCentroid.multiply(pyramidVolume); volume += pyramidVolume; } // Average the weighted sum of pyramid centroids. centroid.divide(volume); 

如果您对此有任何疑问,请随时向我询问,或者指出您看到的任何错误。

通常,这取决于多面体的结构。 有4种可能的情况:

  • 只有顶点具有权重,即您的多面体是点系统。 然后你可以计算所有点的加权和的平均值:

     r_c = sum(r_i * m_i) / sum(m_i) 

    这里r_i是表示第i个顶点的向量, m_i – 它的质量。 同等群众的情况给我们留下了更简单的公式:

     r_c = sum(r_i) / n 

    其中n是顶点数。 请注意,两个总和都是矢量化的。

  • 只有边缘有重量,多面体基本上是一个胴体。 通过用位于边缘中间的顶点替换每个边缘并且具有整个边缘的权重,可以将这种情况简化为前一个边缘。

  • 只有脸有重量。 这种情况也可以减少到第一种情况。 每个面都是2D凸面图,其中可以找到质心。 用它的质心代替每个面将这种情况带到第一个面。

  • 实心多面体(您的情况,从“假设均匀密度”推断)。 这个问题需要更复杂的方法。 第一步是将多面体分割成四面体。 以下是如何执行此操作的简短说明 。 对于四面体质心位于其所有中位数相交的点。 (四面体的中位数是连接其顶点和相对面的质心的线。)下一步是用分区替换分区中的每个四面体。 最后一步是找到所得加权点集的质心,这正是第一种情况。

对于实体情况,有一种比尝试四面体化多面体(有缺陷 ) 更简单的方法 。

这是伪ish java-ish代码(假设正常的Vector3实现):

 // running sum for total volume double vol = 0; // running sum for centroid Vector3 centroid = (0, 0, 0); for each triangle (a,b,c) { // Compute area-magnitude normal Vector3 n = (ba).cross(ca); vol += a.dot(n)/6.; // Compute contribution to centroid integral for each dimension for(int d = 0;d<3;d++) centroid[d] += n[d] * ((a[d]+b[d])^2 + (b[d]+c[d])^2 + (c[d]+a[d])^2); } // final scale by inverse volume centroid *= 1./(24.*2.*vol); 

请注意,如果您拥有比三角形更高的度数面,则可以使用扇形进行三角测量,这仍然有效。

即使多面体不凸出,这也很方便。

我还发布了matlab代码