Center of gravity / mass (centroid)

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
josh
DevNet Master
Posts: 4872
Joined: Wed Feb 11, 2004 3:23 pm
Location: Palm beach, Florida

Center of gravity / mass (centroid)

Post 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));
}
Last edited by josh on Tue Nov 04, 2008 7:37 pm, edited 1 time in total.
User avatar
pickle
Briney Mod
Posts: 6445
Joined: Mon Jan 19, 2004 6:11 pm
Location: 53.01N x 112.48W
Contact:

Post by pickle »

Obscure, but frickin' cool!
Real programmers don't comment their code. If it was hard to write, it should be hard to understand.
User avatar
John Cartwright
Site Admin
Posts: 11470
Joined: Tue Dec 23, 2003 2:10 am
Location: Toronto
Contact:

Post by John Cartwright »

Okay I have to ask now.. what are you working on :P
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post 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 :)
josh
DevNet Master
Posts: 4872
Joined: Wed Feb 11, 2004 3:23 pm
Location: Palm beach, Florida

Post 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:
dismissedasdrone
Forum Newbie
Posts: 1
Joined: Fri Mar 17, 2006 8:17 pm

Re: Center of gravity / mass (centroid)

Post 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!

*
Post Reply