Centroid of a convex polyhedron

I have a closed convex polyhedron, which is defined by an array of convex polygons (faces), which are defined by arrays of vertices in three-dimensional space. I am trying to find the center of gravity of a polyhedron, assuming uniform density. At the moment, I am calculating it using an algorithm in this pseudo-code.

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; } 

This essentially takes a weighted average of the centroids of the faces. I am not 100% sure, this is correct, since I could not find the correct algorithm online. If someone could confirm my algorithm or direct me to the correct one, I would appreciate it.

Thanks.


[EDIT]

So, here is the actual Java code that I use to find the centroid. It divides the polyhedron into pyramids converging at an arbitrary point inside the polyhedron. The weighted average for the centroids of the pyramid is based on the following formula.

C all = SUM all pyramids (C pyramid * volume pyramid ) / volume allsub>

Here (heavily commented code):

  // 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); 

Please feel free to ask me any questions you may have about this or point out any errors you see.

+7
source share
2 answers

This usually depends on the structure of your polyhedron. 4 cases are possible:

+7
source

For the hard case, there is a much simpler method than trying to tetrahedronize a polyhedron (which is a trap ).

Here's the java-ish pseudo-hash code (assuming a decent implementation of 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); 

Note that if you have higher degree faces than triangles, you can trivially using a fan is trivial, and this will work anyway.

This works conveniently even if the polyhedron is not convex.

I also posted matlab code

+2
source

All Articles