Centre of mass convenience functions
Posted: Sun Jul 11, 2010 3:31 pm
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:
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/
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;
}
1. http://en.wikipedia.org/wiki/Centroid#C ... of_polygon
2. http://cnx.org/content/m14120/latest/