Центроид выпуклого многогранника

У меня есть замкнутый выпуклый многогранник, который определяется массивом выпуклых многоугольников (граней), которые определяются массивами вершин в трехмерном пространстве. Я пытаюсь найти центр тяжести многогранника, предполагая однородную плотность. На данный момент я рассчитываю это с помощью алгоритма в этом псевдокоде.

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%, что это правильно, поскольку мне не удалось найти правильный алгоритм в Интернете. Если бы кто-то мог подтвердить мой алгоритм или направить меня к правильному, я был бы признателен.

Спасибо.


[EDIT]

Вот реальный код 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);

Пожалуйста, не стесняйтесь задавать мне любые вопросы по этому поводу или указывать на любые обнаруженные вами ошибки.

7
задан null0pointer 17 February 2012 в 14:09
поделиться