At 11:24 PM 1/21/02 +0100, Eric wrote:

>The most common way is done thru dot products or (quite identical) signed
>area :

That's a great technique, but it's a lot of work to process large polygons 
because you have to do the arithmetic at every vertex.  It strikes me that 
a task as conceptually simple as determining polygon orientation ought to 
require less computation.  I found a way by cheating slightly.  In systems 
that maintain minimum bounding rectangle (MBR) information--I believe 
MapInfo is one of them--there is a faster method.  Loop over the vertices 
until you find one whose Y coordinate equals the minimum Y 
coordinate.  This vertex is at the bottom of the polygon, so just check 
whether the polygon is being drawn left-to-right or right-to-left at this 
point to determine whether it is counterclockwise or clockwise, 
respectively.  This works except when the vertex found is the tip of a 
zero-area sliver, which should not occur.  On the average you have to check 
only half the vertices and the arithmetic is the fastest possible: a simple 
comparison of two numbers.

Here are the details.  Assuming the polygon is connected, it can be 
represented as an array P[0..N+1] of points where P[0] = P[N] and P[1] = 
P[N+1].  Let the known minimum Y coordinate obtained from the MBR be 
y0.  Assuming there is a function Norm(p) = sqrt(p.x^2 + p.y^2) for the 
lengths of vectors, then the C-like pseudo-code is short and elegant:

         for (i=1; i <=N && P[i].y > y0; i++) {}
         e = P[i] - P[i-1]
         f = P[i+1] - P[i]
         return Norm(e)*f.x + Norm(f)*e.x > 0     /* If this expression is 
zero, there is a problem. */

This function returns true for counterclockwise polygons and false 
otherwise.  It's easily implemented in MapBasic.

A production program has to cope with invalid input.  The "i<=N" part 
prevents endless looping if y0 is incorrect.  After the loop, check for 
this condition with i==N+1.  (If y0 is guaranteed correct, then removing 
the "i<=N" check could double the speed of the program.)  If the expression 
"Norm(e)*f.x + Norm(f)*e.x" is zero, then P[i] is the tip of a zero-area 
sliver.  Thus you can reliably detect many bad inputs and bullet-proof your 
code.

It would be interesting to find a solution that is even more efficient than 
this one.

Cheers,
Bill Huber





_______________________________________________________________________
List hosting provided by Directions Magazine | www.directionsmag.com |
To unsubscribe, send e-mail to [EMAIL PROTECTED] and
put "unsubscribe MapInfo-L" in the message body.

Reply via email to