[postgis-users] shp2pgsql inner/outer ring detection bug FIX
strk
strk at freek.keybit.net
Sat Jan 4 01:22:41 PST 2003
>From "ESRI Shapefile Technical Description" (An ESRI White Paper-July 1998):
first-vertex must be equal to last-vertex in the following cases:
- rings in Multipatch shapes
- rings of PolygonZ shapes
- rings of PolygonM shapes
- rings of Polygon shapes
This is expressed in the "Notes" section for each shape type description:
> [..]
> The rings are closed (the first and last vertex of a ring MUST be the same).
> [..]
--strk;
~
strk wrote:
> I'm sorry but you got me wrong: the bug is NOT in postgis_fn.c, but
> in loader/shp2pgsql.c. There is a PIP function also there with the
> loop check running while i<n ... It is for the rest identical to
> the one you posted here (apart from vt declared inside the loop and
> itscomputatio casted to (float)).
>
> I'm not familiar with shapelib code myself, I'll check the
> last-vertex issue, however even if the last vertex != first vertex
> referencing V[n] will go past the allocated memory for the
> array... in this case shp2pgsql should check the value of i
> and using V[i], V[0] when i=n-1.
>
> --strk;
>
> dblasby wrote:
> > > 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)
> >
> > }
> >
> >
> > _______________________________________________
> > postgis-users mailing list
> > postgis-users at postgis.refractions.net
> > http://postgis.refractions.net/mailman/listinfo/postgis-users
>
> _______________________________________________
> postgis-users mailing list
> postgis-users at postgis.refractions.net
> http://postgis.refractions.net/mailman/listinfo/postgis-users
More information about the postgis-users
mailing list