The thing is you don't have to physically re-order the array, and you're not going to sort it.
You iterate it once, checking for a larger North South East and West than you've already found, and updating those if the current point exceeds them.
Code:
$maxNorth = $maxEast = $maxSouth = $maxWest = 0;
$maxNorthIdx = $maxEastIdx = $maxSouthIdx = $maxWestIdx = 0;
for($i=0; $i<count($points); $i++) {
if ($points[$i]['longitude'] < $maxWest) {
$maxWest = $points[$i]['longitude'];
$maxWestIdx = $i;
}
else if ($points[$i]['longitude'] > $maxEast) {
$maxEast = $points[$i]['longitude'];
$maxEastIdx = $i;
}
if ($points[$i]['latitude'] < $maxSouth) {
$maxSouth = $points[$i]['latitude'];
$maxSouthIdx = $i;
}
else if ($points[$i]['latitude'] > $maxNorth) {
$maxNorth = $points[$i]['latitude'];
$maxNorthIdx = $i;
}
}
$offset = $maxNorthIdx; // alias all indexes by this amount
Then you alias the starting point from index '0' to Point
North - so for example, if
North is originally at index 4500, and the total number of points in the array is 5000, all point indexes simply have an integer
offset subtracted from them, with simple logic to detect the wrap around using modulo
array size:
0 Point A
1 Point B
2 Point C
...
500 Point
West...
2000 Point
South...
3000 Point
East...
4500 Point
North...
5000 Point Z
The offset is therefore
4500So for any given Point, it's index is:
$index = ($index - $offset) < 0 ? ($index - $offset) + 5000 : $index - $offset;So with no re-arranging of the array, we can calculate the
West and
East indexes and therefore the
winding direction:
Code:
$West = ($maxWestIdx-offset) < 0 ? ($maxWestIdx-$offset)+5000 : $maxWestIdx-$offset;
$East = ($maxEastIdx-offset) < 0 ? ($maxEastIdx-$offset)+5000 : $maxEastIdx-$offset;
$CCW = $West < $East ? 1 : 0; // set boolean flags to indicate winding direction
$CW = $West < $East ? 0 : 1;
This all supposes the algorithm is robust. For the cases I'm working with it works and is very fast, but I'm sure someone out there can show it falls down in some cases - the thing is, finding out when that happens, and whether those cases can be predicted and corrected.
As long as all the points are on or near the same plane it seems as it it will be reliable enough - certainly for working with GE Polygons. And it meets my criteria -
easy to implement and fast.
As to the more general mathematical proofs, I'll leave that for the people that find that stuff entertaining