Page 1 of 1

Centre of mass convenience functions

Posted: Sun Jul 11, 2010 3:31 pm
by Ostsol
In recent experiments I discovered for myself the oddity of what happens when one does not set a shape's position on the a body at the centre of mass. I had hoped that Chipmunk provided some functionality that would allow me to quickly discover an object's centre of mass, but I could not find any. For circles and rectangles it is trivial, but polygons represent a slightly more complex issue. To add further complexity, a body may have multiple shapes attached to it, and said shapes may not have the same mass. Based on the equations found on two websites ([1], [2]) I have produced the following simple program:

Code: Select all

#include <stdio.h>

typedef struct {
    float x, y;
} Vect;

float area(Vect points[], int count) {
    float sum = 0.0;

    int i;
    for (i = 0; i < count; i++) {
        int j = (i < count-1) ? i+1 : 0;

        Vect p0 = points[i];
        Vect p1 = points[j];

        sum += p0.x*p1.y - p1.x*p0.y;
    }

    return 0.5*sum;
}

Vect centroid(Vect points[], int count) {
    Vect c;
    c.x = c.y = 0.0;
    float a = area(points, count);

    int i;
    for (i = 0; i < count; i++) {
        int j = (i < count-1) ? i+1 : 0;

        Vect p0 = points[i];
        Vect p1 = points[j];
        
        c.x += (p0.x + p1.x) * (p0.x*p1.y - p1.x*p0.y);
        c.y += (p0.y + p1.y) * (p0.x*p1.y - p1.x*p0.y);
    }

    c.x = 1.0/(6.0*a) * c.x;
    c.y = 1.0/(6.0*a) * c.y;

    return c;
}

// find the centroid for an object made up of two other shapes, given the
// centroid and mass for each.
Vect composite_centroid(Vect c0, float m0, Vect c1, float m1) {
    Vect c;
    c.x = (m0*c0.x + m1*c1.x) / (m0 + m1);
    c.y = (m0*c0.y + m1*c1.y) / (m0 + m1);

    return c;
}

int main(int argc, char *args[]) {
    Vect poly0[] = {{0.0, 2.0}, {1.0, 2.0}, {1.0, 0.0}, {0.0, 0.0}};
    float m0 = 10.0;
    Vect c0 = centroid(poly0, 4);
    printf("c0 = (%f, %f)\n", c0.x, c0.y);
    
    Vect poly1[] = {{1.0, 2.0}, {2.0, 2.0}, {2.0, 0.0}, {1.0, 0.0}};
    float m1 = 20.0;
    Vect c1 = centroid(poly1, 4);
    printf("c1 = (%f, %f)\n", c1.x, c1.y);
    
    Vect poly2[] = {{2.0, 2.0}, {3.0, 2.0}, {3.0, 0.0}, {2.0, 0.0}};
    float m2 = 10.0;
    Vect c2 = centroid(poly2, 4);
    printf("c2 = (%f, %f)\n", c2.x, c2.y);
    
    Vect c01 = composite_centroid(c0, m0, c1, m1);
    printf("c0 + c1 = (%f, %f)\n", c01.x, c01.y);

    Vect c012 = composite_centroid(c01, m0+m1, c2, m2);
    printf("c0 + c1 + c2 = (%f, %f)\n", c012.x, c012.y);

    return 0;
}
Would it be possible for similar functions to be included in a future release of the library?

1. http://en.wikipedia.org/wiki/Centroid#C ... of_polygon
2. http://cnx.org/content/m14120/latest/