Jump to content

Like
0Likes
Dislike
Point in a poly


point winding number lastpt int orig thispt wind quad

4: Adsense

Robert's suggestion is a good one. The sum of the angles about the test point is known as the winding number. For non intersecting polygons if the winding number is non-zero then the test point is inside the polygon. It works just fine for convex and concave polygon's. Intersecting polygon's give reasonable results too. A figure 8 will give a negitive winding number for a test point in one of the loops and a positive winding number for the other loop, with all points outside having a winding number of 0. Other advantages of the winding number calculation are that it does not suffer from the confusion of the infinite ray algorithm when the ray crosses a vertex or is colinear with an edge.

Here is my version of a point in poly routine using a quadrant granularity winding number. The basic idea is to total the angle changes for a wiper arm with its origin at the point and whos end follows the polygon points. If the angle change is 0 then you are outside, otherwise you are in some sense inside. It is not necessary to compute exact angles, resolution to a quadrant is sufficient, greatly simplifying the calculations.

I pulled this out of some other code and hopefully didn't break it in doing so. There is some ambiguity in this version as to whether a point lying on the polygon is inside or out. This can be fairly easily detected though, so you can do what you want in that case.

-----------------------------------------------------------------
/*
 * Quadrants:
 *    1 | 0
 *    -----
 *    2 | 3
 */

typedef struct  {
        int x,y;
} point;

pointinpoly(pt,cnt,polypts)
point pt;   	/* point to check */
int cnt;        /* number of points in poly */
point *polypts; /* array of points, */
                /* last edge from polypts[cnt-1] to polypts[0] */
{
        int oldquad,newquad;
        point thispt,lastpt;
        int a,b;
        int wind;   	/* current winding number */

        wind = 0;
        lastpt = polypts[cnt-1];
        oldquad = whichquad(lastpt,pt); /* get starting angle */
        for(i=0;i
                thispt = polypts[i];
                newquad = whichquad(thispt,pt);
                if(oldquad!=newquad) { /* adjust wind */
                        /*
                     	* use mod 4 comparsions to see if we have
                     	* advanced or backed up one quadrant 
                     	*/
                        if(((oldquad+1)&3)==newquad) wind++;
                        else if((((newquad+1)&3)==oldquad) wind--;
                        else {
                                /*
                             	* upper left to lower right, or
                             	* upper right to lower left. Determine
                             	* direction of winding  by intersection
                             	*  with x==0.
                             	*/
                                a = lastpt.y - thispt.y;
                                a *= (pt.x - lastpt.x);
                                b = lastpt.x - thispt.x;
                                a += lastpt.y * b;
                                b *= pt.y;

                                if(a > b) wind += 2;
                                else wind -= 2;
                        }
                }
                lastpt = thispt;
        }
        return(wind); /* non zero means point in poly */
}

/*
 * Figure out which quadrent pt is in with respect to orig
 */
int whichquad(pt,orig)
point pt;
point orig;
{
        if(pt.x < orig.x) {
                if(pt.y < orig.y) quad = 2;
                else quad = 1;
        } else {
                if(pt.y < orig.y) quad = 3;
                else quad = 0;
        }
}
Ken McElvain
decwrl!sci!kenm

0 Comments

Note: GameDev.net moderates article comments.