I'd suggest a much simpler approach. Start with any outer edge, say P1->P2. Then you check each node PX connected to P2, and pick the one where the angle (P1,P2,PX) has the smallest positive value. That node PX is the next node in your polygon. Then go on finding the node PY connected to PX where the angle (P2,PX,PY) has the smallest positive value.
There are several possible approaches to calculating the angle. One would be:
c = inner_product( P1-P2, PX-P2 ) / ( abs(P1-P2) * abs(PX-P2) ) # cosine of the angle
s = cross_product( P1-P2, PX-P2 ) / ( abs(P1-P2) * abs(PX-P2) ) # sine of the angle
angle = atan2( s, c ) # arc tangent with correct sign
With:
def cross_product( a, b ):
return a.x*b.y - a.y * b.x
def inner_product( a, b ):
return a.x*b.x + a.y*b.y
Be careful with the sign, it depends on CW vs CCW. And of course you can omit the normalization terms (abs...
), because they cancel each other.
If concave polygons are allowed, you have to re-normalize the result of the arc tangent in order to ensure the angle is always positive:
def atan2_normalized( y, x ):
angle = atan2( y, x )
if angle < 0:
return angle + 2 * Pi
else:
return angle