Page 1 of 1

Center of gravity / mass (centroid)

Posted: Sun Feb 12, 2006 9:08 pm
by josh
This code will locate the center of gravity (also known as centroid) on any non-self-intersecting polygon


ex.
Image

Code: Select all

function centroid($polygon,$n) {
    
    $a = area($polygon,$n);
 
    $cx = 0;
    $cy = 0;
    
    $polygon=array_chunk($polygon,2);
    
    for ($i=0;$i<$n;$i++) {
        $cx += ($polygon[$i][0] + $polygon[$i+1][0]) * ( ($polygon[$i][0]*$polygon[$i+1][1]) - ($polygon[$i+1][0]*$polygon[$i][1]) );
        $cy += ($polygon[$i][1] + $polygon[$i+1][1]) * ( ($polygon[$i][0]*$polygon[$i+1][1]) - ($polygon[$i+1][0]*$polygon[$i][1]) );
    }
 
    return(array( (1/(6*$a))*$cx,(1/(6*$a))*$cy));
    
}
function area($polygon,$n) {
    // based off my function here:
    // viewtopic.php?t=41715&highlight=vertex+ordering
    $polygon=array_chunk($polygon,2);
    $area = 0;
    for ($i=0;$i<$n;$i++) {
        $j = ($i + 1);
        $area += $polygon[$i][0] * $polygon[$j][1];
        $area -= $polygon[$i][1] * $polygon[$j][0];
    }
    $area /= 2;
    return(abs($area));
}

Posted: Mon Feb 13, 2006 10:42 am
by pickle
Obscure, but frickin' cool!

Posted: Mon Feb 13, 2006 10:45 am
by John Cartwright
Okay I have to ask now.. what are you working on :P

Posted: Mon Feb 13, 2006 11:17 am
by Chris Corbyn
Jcart wrote:Okay I have to ask now.. what are you working on :P
I've asked this in a similar thread... must be a top secret government mission I think. Either that, or we have student doing a physics degree with the ability to do coursework in PHP :)

Posted: Mon Feb 13, 2006 11:36 am
by josh
Refer to my post about a google maps (kind of) clone in the "let's show off" thread.. lotta geometry work is involved and there was little resources so I'm sharing code snippets that woulda helped me, something like this is useful for finding the center of a land mass for labelling it or whatever you need to do. The code snippet about the vertex ordering is because polygons ordered counter-clockwise define a hole inside of it's parent polygon (land mass with a lake in the middle for example), it gets really confusing when they nest holes inside holes to an arbitrary number. Heh, I'm sure someone will have a use for this.


~~~~~~~
d11wtq wrote:[must be a top secret government mission
Yeah, the governments still stuck on two dimensional polygons, its completely over their heads :lol:

Re: Center of gravity / mass (centroid)

Posted: Fri Mar 17, 2006 8:50 pm
by dismissedasdrone
jshpro2 wrote:This code will locate the center of gravity (also known as centroid) on any non-self-intersecting polygon
Wow, thanks for posting this. Saved me the time of converting an old C routine into PHP!

As a side note, for those of you that are just looking for relative results and aren't worried about mapping a car full of kids into a lake, you can simply average the verticies for an approximate result.

e.g.

Image

Code: Select all

<?php

        $x = $y = 0; // For those running with Notices on...

$poly = array(
                 50,50,  75,200, 100,200, 20,250, 350,200,
                300,80, 280,40,  200,20, 100,60
              );

        $polygon = array_chunk($poly,2); // Chunk Array in coords
        $n       = count($polygon);      // Calc Once

        for($i=0;$i<$n;$i++)
        {
                $x+=$polygon[$i][0];
                $y+=$polygon[$i][1];
        }
        $x = round($x/$n); $y = round($y/$n);
        echo "X = {$x}, Y = {$y}";
?>
or as a function:

Code: Select all

function polyCenter($polygon)
{
        ## IN: array of coordinates ##
        $p = array_chunk($polygon,2);
        $n       = count($p);

        for($i=0;$i<$n;$i++)
        {
                $x+=$p[$i][0];
                $y+=$p[$i][1];
        }
        ## OUT: X,Y coordinates of approx center in array ##
        return array(round($x/$n),round($y/$n));
}

Thanks again!

*