Finding the center of mass on a 2D bitmap

前端 未结 3 1876
萌比男神i
萌比男神i 2020-12-31 13:54

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..X         


        
相关标签:
3条回答
  • 2020-12-31 14:19

    You could count the number of adjoining cells, then center on the cells with the highest neighbor count.

     012345678
    0 XX      |
    1  XXX    |
    2   XXX   |
    3  XXXXXXX|
    4   XXX   |
    
     012345678
    0 23      |
    1  454    |
    2   775   |
    3  3686421|
    4   454   |
    

    In this example you could use the only cell with an 8, as the center point.

    If you came up with multiple cells with the same number of neighbors, you would just run the counting routine again, but this time just with the high number cells.

    For example, lets pretend that the cells that had 6, 7, and 8, instead all had eight neighbors.

     012345678
    0 23      |
    1  454    |
    2   885   |
    3  3888421|
    4   454   |
    
     012345678
    0 --      |
    1  ---    |
    2   XX-   |
    3  -XXX---|
    4   ---   |
    
     012345678
    0 --      |
    1  ---    |
    2   34-   |
    3  -342---|
    4   ---   |
    
     012345678
    0 --      |
    1  ---    |
    2   -X-   |
    3  --X----|
    4   ---   |
    

    In the case of a simple tie, I would go with the one that was nearer the center. In this case it would be the upper one of the two.

    Note: I'm assuming your not using this for an accurate physics simulation.

    0 讨论(0)
  • 2020-12-31 14:21

    How about this algorithm (psuedo-code) based on a boolean matrix like in your example :

    xSum = 0
    ySum = 0
    points = 0
    
    for point in matrix
        if point is marked
            xSum += pointX
            ySum += pointY
            points++
    
    return (xSum/points, ySum/points)
    

    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

    0 讨论(0)
  • 2020-12-31 14:35

    Depending on the nature of your actionscript interpreter and the pre-processing done on the shapes, you may see a speed improvement (over the direct approach pointed out by Yuval) by initially creating a second copy of the bitmap/array mirrored diagonally, then using row or string manipulation functions to sum the points on each row and column in single steps. This would be O(2mn) instead of O(nn) [see below], but with more overhead.

    xSum = 0
    ySum = 0
    points = 0
    
    for row in matrix
      ySum += rowX * countpoints(row)
      points += countpoints(row)
    for row in mirroredmatrix
      xSum += rowX * countpoints(row)
    
    return (xSum/points, ySum/points)
    

    Where countpoints() counts the on-points in a row. This relies on countpoints (which has O(n) runtime) having a lower constant multiplier than the naive approach's runtime (hence above, 'm' being the runtime of countpoints and 'n' being the time for the interpreter to loop through a row). The nature of countpoints() depends on your storage method, which may involve counting characters in a string, or bits in a bitfield.

    0 讨论(0)
提交回复
热议问题