I’m coding a game, and I’d like to be able to find the center of mass of an arbitrary shape on a black and white bitmap such as this:
012345678 0.XX...... 1..XXX.... 2...XXX... 3..XXXXXXX 4...XXX...
All ‘cells’ have the same weight. Diagonally adjacent cells are not considered to be connected, and the shape will always be a single one since it’s already split by another function before this.
It’s only going to be used for reasonably low resolution (maybe 50×50 at most) images and it doesn’t need to be super accurate, speed is preferable.
I get a feeling there’s a proper way to do this, but I don’t really know what to google for.
I’m coding this in Actionscript 3, but examples in any language are appreciated, moreso if they’re made to be understood by humans.
EDIT: Feel free to assume that the data is stored in whatever data structure you think is most convenient for your example. I’m using bitmaps, but two-dimensional arrays or even a single array is just fine too!
EDIT: This is the code I ended up using, it can most likely be done faster, but I find this to be very readable:
// _bmp is a private BitmapData instance public function getCenterOfMass():Point { var avg :Point = new Point(0, 0); var points :uint = 0; for (var ix:uint = 0; ix < _bmp.width; ix++) { for (var iy:uint = 0; iy < _bmp.height; iy++) { if (_bmp.getPixel(ix, iy) == ACTIVE_COLOR) { avg.x += ix; avg.y += iy; points++; } } } avg.x /= points; avg.y /= points; return avg; }
How about this algorithm (psuedo-code) based on a boolean matrix like in your example :
Nothing too complicated, calculate where X is the most present, same for Y, divide by number of points you counted, and you got the center of mass. You can further complicate this by giving certain points different weight in the averaging, but this should be your main direction.
This question got me thinking about an expansion to this question which I could not find a good answer to. I posted the question here: Finding clusters of mass in a matrix/bitmap