in commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/AbstractConvexPolygon3D.java [98:150]
public Vector3D getCentroid() {
final List<Vector3D> vertices = getVertices();
double areaSum = 0.0;
double scaledCentroidSumX = 0.0;
double scaledCentroidSumY = 0.0;
double scaledCentroidSumZ = 0.0;
final Iterator<Vector3D> it = vertices.iterator();
final Vector3D startPt = it.next();
Vector3D prevPt = it.next();
Vector3D curPt;
Vector3D prevVec = startPt.vectorTo(prevPt);
Vector3D curVec;
double triArea;
Vector3D triCentroid;
while (it.hasNext()) {
curPt = it.next();
curVec = startPt.vectorTo(curPt);
triArea = 0.5 * prevVec.cross(curVec).norm();
triCentroid = Vector3D.centroid(startPt, prevPt, curPt);
areaSum += triArea;
scaledCentroidSumX += triArea * triCentroid.getX();
scaledCentroidSumY += triArea * triCentroid.getY();
scaledCentroidSumZ += triArea * triCentroid.getZ();
prevPt = curPt;
prevVec = curVec;
}
if (areaSum > 0) {
final double scale = 1 / areaSum;
return Vector3D.of(
scale * scaledCentroidSumX,
scale * scaledCentroidSumY,
scale * scaledCentroidSumZ
);
}
// zero area, which means that the points are all linear; return the point midway between the
// min and max points
final Vector3D min = Vector3D.min(vertices);
final Vector3D max = Vector3D.max(vertices);
return min.lerp(max, 0.5);
}