[postgis-users] shp2pgsql inner/outer ring detection bug FIX

David Blasby dblasby at refractions.net
Fri Jan 3 09:40:17 PST 2003


> Anyway for my case shapefile was not "dirty". The PIP function was ...
>
> Checking the same function in postgis_fn.c I've found the bug:
> the edge loop check has to be i<(n-1) instead of i<n
> Fixing this everything works fine.

I dont think this is correct - the V array has n points in it - V[0] ... V[n-1]

If you change "i<(n-1)" to "i<n" then (in the loop), "i" will eventually get to be
the value (n-1).

The V[i+1] reference will then be V[(n-1)+1] = V[n] which is past the end of the
array (bad news).

"i" is the edge number - there are (n-1) edges in a [PostGIS] polygon that has the
1st point = last point.

Now, I've looked at the shapefile spec, and it doesnt seem to say that the first
point of a polygon must equal the last point.

So, I think the postgis code is correct (could you verify that for me?), but the
shapefile code maybe not checking the last edge (connecting the last point to the
first point).  I'm not familiar with the shapefile code....

dave




int PIP( POINT3D *P, POINT3D *V, int n )
{
    int    cn = 0;    // the crossing number counter
   int i;

 double vt;

    // loop through all edges of the polygon

     for (i=0; i< (n-1) ; i++)
 {    // edge from V[i] to V[i+1]

        if (((V[i].y <= P->y) && (V[i+1].y > P->y))    // an upward crossing
          || ((V[i].y > P->y) && (V[i+1].y <= P->y))) // a downward crossing
   {

           vt = (double)(P->y - V[i].y) / (V[i+1].y - V[i].y);
             if (P->x < V[i].x + vt * (V[i+1].x - V[i].x))    // P.x <intersect
                   ++cn;   // a valid crossing of y=P.y right of P.x
       }
    }
    return (cn&1);    // 0 if even (out), and 1 if odd (in)

}




More information about the postgis-users mailing list