From: Sandro Santilli Date: Tue, 22 Nov 2005 21:26:39 +0000 (+0000) Subject: Fixed a bug in getPoint{3dm,3dz,4d}_p() api calls automatically X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f2001228604bfbaf17044a52c2bb5d73a0273870;p=postgis Fixed a bug in getPoint{3dm,3dz,4d}_p() api calls automatically fixing bugs in force_{3dm,3dz,4d}() user functions. Wrapped paranoid checks in PARANOIA_LEVEL preprocessor blocks. Updated release notes and CHANGES file. git-svn-id: http://svn.osgeo.org/postgis/branches/pgis_1_0@2052 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/CHANGES b/CHANGES index 4591cff73..bec3919af 100644 --- a/CHANGES +++ b/CHANGES @@ -10,6 +10,7 @@ PostGIS 1.0.5CVS - Fixed a small bug in the getPoint4d_p() low-level function - Fixed memory alignment problems - Speedup of serializer functions + - Bug fix in force_4d, force_3dm and force_3dz functions PostGIS 1.0.4 2005/09/09 diff --git a/doc/postgis.xml b/doc/postgis.xml index 1c7d8b343..7375b52b9 100644 --- a/doc/postgis.xml +++ b/doc/postgis.xml @@ -4873,6 +4873,7 @@ standards (return 0 on success). Fixed computation of null values fraction in analyzer Fixed a small bug in the getPoint4d_p() low-level function Speedup of serializer functions + Fixed a bug in force_3dm(), force_3dz() and force_4d() diff --git a/lwgeom/liblwgeom.h b/lwgeom/liblwgeom.h index d5bfefabf..2632edcb9 100644 --- a/lwgeom/liblwgeom.h +++ b/lwgeom/liblwgeom.h @@ -269,7 +269,7 @@ extern void lwgeom_dropSRID(LWGEOM *lwgeom); // copies a point from the point array into the parameter point // will set point's z=0 (or NaN) if pa is 2d -// will set point's m=0 (or NaN( if pa is 3d or 2d +// will set point's m=0 (or NaN) if pa is 3d or 2d // NOTE: point is a real POINT3D *not* a pointer extern POINT4D getPoint4d(const POINTARRAY *pa, int n); diff --git a/lwgeom/lwgeom_api.c b/lwgeom/lwgeom_api.c index 15c363e3d..e6fc8534d 100644 --- a/lwgeom/lwgeom_api.c +++ b/lwgeom/lwgeom_api.c @@ -7,6 +7,11 @@ #include "liblwgeom.h" +/* + * Lower this to reduce integrity checks + */ +#define PARANOIA_LEVEL 1 + //#define PGIS_DEBUG 1 // This is an implementation of the functions defined in lwgeom.h @@ -426,14 +431,16 @@ getPoint4d(const POINTARRAY *pa, int n) } // copies a point from the point array into the parameter point -// will set point's z=0 (or NaN) if pa is 2d -// will set point's m=0 (or NaN( if pa is 3d or 2d +// will set point's z=NO_Z_VALUE if pa is 2d +// will set point's m=NO_M_VALUE if pa is 3d or 2d // NOTE: this will modify the point4d pointed to by 'point'. int -getPoint4d_p(const POINTARRAY *pa, int n, POINT4D *point) +getPoint4d_p(const POINTARRAY *pa, int n, POINT4D *op) { - int size; + uchar *ptr; + int zmflag; +#if PARANOIA_LEVEL > 0 if ( ! pa ) return 0; if ( (n<0) || (n>=pa->npoints)) @@ -441,11 +448,41 @@ getPoint4d_p(const POINTARRAY *pa, int n, POINT4D *point) lwerror("getPoint4d_p: point offset out of range"); return 0; //error } +#endif + + /* Get a pointer to nth point offset and zmflag */ + ptr=getPoint_internal(pa, n); + zmflag=TYPE_GETZM(pa->dims); + + switch (zmflag) + { + case 0: // 2d + memcpy(op, ptr, sizeof(POINT2D)); + op->m=NO_M_VALUE; + op->z=NO_Z_VALUE; + break; + + case 3: // ZM + memcpy(op, ptr, sizeof(POINT4D)); + break; + + case 2: // Z + memcpy(op, ptr, sizeof(POINT3DZ)); + op->m=NO_M_VALUE; + break; + + case 1: // M + memcpy(op, ptr, sizeof(POINT3DM)); + op->m=op->z; // we use Z as temporary storage + op->z=NO_Z_VALUE; + break; + + default: + lwerror("Unkown ZM flag ??"); + } - memset(point, 0, sizeof(POINT4D)); - size = pointArray_ptsize(pa); - memcpy(point, getPoint_internal(pa, n), size); return 1; + } @@ -478,64 +515,109 @@ getPoint3dm(const POINTARRAY *pa, int n) int getPoint3dz_p(const POINTARRAY *pa, int n, POINT3DZ *op) { - int size; + uchar *ptr; +#if PARANOIA_LEVEL > 0 if ( ! pa ) return 0; + if ( (n<0) || (n>=pa->npoints)) + { + lwnotice("%d out of numpoint range (%d)", n, pa->npoints); + return 0; //error + } +#endif + #ifdef PGIS_DEBUG lwnotice("getPoint3dz_p called on array of %d-dimensions / %u pts", TYPE_NDIMS(pa->dims), pa->npoints); #endif - if ( (n<0) || (n>=pa->npoints)) + /* Get a pointer to nth point offset */ + ptr=getPoint_internal(pa, n); + + /* + * if input POINTARRAY has the Z, it is always + * at third position so make a single copy + */ + if ( TYPE_HASZ(pa->dims) ) { - lwnotice("%d out of numpoint range (%d)", n, pa->npoints); - return 0; //error + memcpy(op, ptr, sizeof(POINT3DZ)); } - /* initialize point */ - memset(op, 0, sizeof(POINT3DZ)); + /* + * Otherwise copy the 2d part and initialize + * Z to NO_Z_VALUE + */ + else + { + memcpy(op, ptr, sizeof(POINT2D)); + op->z=NO_Z_VALUE; + } - /* copy */ - size = pointArray_ptsize(pa); -#ifdef PGIS_DEBUG - lwnotice("getPoint3dz_p: point size: %d", size); -#endif - memcpy(op, getPoint_internal(pa, n), size); return 1; } // copies a point from the point array into the parameter point -// will set point's m=NO_Z_VALUE if pa has no M +// will set point's m=NO_M_VALUE if pa has no M // NOTE: this will modify the point3dm pointed to by 'point'. int getPoint3dm_p(const POINTARRAY *pa, int n, POINT3DM *op) { - int size; + uchar *ptr; + int zmflag; +#if PARANOIA_LEVEL > 0 if ( ! pa ) return 0; + if ( (n<0) || (n>=pa->npoints)) + { + lwerror("%d out of numpoint range (%d)", n, pa->npoints); + return 0; //error + } +#endif + #ifdef PGIS_DEBUG lwnotice("getPoint3dm_p(%d) called on array of %d-dimensions / %u pts", n, TYPE_NDIMS(pa->dims), pa->npoints); #endif - if ( (n<0) || (n>=pa->npoints)) + + /* Get a pointer to nth point offset and zmflag */ + ptr=getPoint_internal(pa, n); + zmflag=TYPE_GETZM(pa->dims); + + /* + * if input POINTARRAY has the M and NO Z, + * we can issue a single memcpy + */ + if ( zmflag == 1 ) { - lwerror("%d out of numpoint range (%d)", n, pa->npoints); - return 0; //error + memcpy(op, ptr, sizeof(POINT3DM)); + return 1; } - /* initialize point */ - memset(op, 0, sizeof(POINT3DM)); + /* + * Otherwise copy the 2d part and + * initialize M to NO_M_VALUE + */ + memcpy(op, ptr, sizeof(POINT2D)); + + /* + * Then, if input has Z skip it and + * copy next double, otherwise initialize + * M to NO_M_VALUE + */ + if ( zmflag == 3 ) + { + ptr+=sizeof(POINT3DZ); + memcpy(&(op->m), ptr, sizeof(double)); + } + else + { + op->m=NO_M_VALUE; + } - /* copy */ - size = pointArray_ptsize(pa); -#ifdef PGIS_DEBUG - lwnotice("getPoint3dz_p: point size: %d", size); -#endif - memcpy(op, getPoint_internal(pa, n), size); return 1; } @@ -547,17 +629,7 @@ POINT2D getPoint2d(const POINTARRAY *pa, int n) { POINT2D result; - int size; - - if ( (n<0) || (n>=pa->npoints)) - { - return result; //error - } - - size = pointArray_ptsize(pa); - - // this does x,y - memcpy(&result.x, &pa->serialized_pointlist[size*n],sizeof(double)*2 ); + getPoint2d_p(pa, n, &result); return result; } @@ -567,21 +639,19 @@ getPoint2d(const POINTARRAY *pa, int n) int getPoint2d_p(const POINTARRAY *pa, int n, POINT2D *point) { - int size; - +#if PARANOIA_LEVEL > 0 if ( ! pa ) return 0; - if ( (n<0) || (n>=pa->npoints)) - { - lwerror("getPoint2d_p: point offset out of range"); - return 0; //error - } - - size = pointArray_ptsize(pa); + if ( (n<0) || (n>=pa->npoints)) + { + lwerror("getPoint2d_p: point offset out of range"); + return 0; //error + } +#endif - // this does x,y - memcpy(point, &pa->serialized_pointlist[size*n],sizeof(double)*2 ); - return 1; + // this does x,y + memcpy(point, getPoint_internal(pa, n), sizeof(POINT2D)); + return 1; } // get a pointer to nth point of a POINTARRAY @@ -592,6 +662,7 @@ getPoint_internal(const POINTARRAY *pa, int n) { int size; +#if PARANOIA_LEVEL > 0 if ( pa == NULL ) { lwerror("getPoint got NULL pointarray"); return NULL; @@ -601,6 +672,7 @@ getPoint_internal(const POINTARRAY *pa, int n) { return NULL; //error } +#endif size = pointArray_ptsize(pa); diff --git a/regress/regress.sql b/regress/regress.sql index f69c120ab..917198e45 100644 --- a/regress/regress.sql +++ b/regress/regress.sql @@ -237,3 +237,8 @@ select '140', asewkt(multi(setsrid('POINT(2 2)'::geometry, 3))); select '141', asewkt(multi(setsrid('LINESTRING(2 2, 3 3)'::geometry, 4))); select '142', asewkt(multi(setsrid('LINESTRING(2 2, 3 3)'::geometry, 5))); select '143', asewkt(multi(setsrid('POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))'::geometry, 6))); + +select '144', asewkt(force_3dm('POINT(1 2 3)')); +select '145', asewkt(force_3dz('POINTM(1 2 3)')); +select '146', asewkt(force_4d('POINTM(1 2 3)')); +select '147', asewkt(force_4d('POINT(1 2 3)')); diff --git a/regress/regress_expected b/regress/regress_expected index 61e77f03f..51874638a 100644 --- a/regress/regress_expected +++ b/regress/regress_expected @@ -143,3 +143,7 @@ ERROR: POSTGIS2GEOS conversion failed 141|SRID=4;MULTILINESTRING((2 2,3 3)) 142|SRID=5;MULTILINESTRING((2 2,3 3)) 143|SRID=6;MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0))) +144|POINTM(1 2 0) +145|POINT(1 2 0) +146|POINT(1 2 0 3) +147|POINT(1 2 3 0)