From: Sandro Santilli Date: Tue, 22 Nov 2005 21:29:41 +0000 (+0000) Subject: Fixed a bug in getPoint{3dm,3dz,4d}_p() api calls automatically X-Git-Tag: pgis_1_1_0~152 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8f417b1c5c0435ed3a0d95b2a64620fd7950c66a;p=postgis Fixed a bug in getPoint{3dm,3dz,4d}_p() api calls automatically fixing bugs in force_{3dm,3dz,4d}() user functions, for which tests have been added in regress dir. Wrapped paranoid checks in PARANOIA_LEVEL preprocessor blocks. Updated release notes and CHANGES file. git-svn-id: http://svn.osgeo.org/postgis/trunk@2053 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/CHANGES b/CHANGES index 092b12e00..730a0ba52 100644 --- a/CHANGES +++ b/CHANGES @@ -35,6 +35,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 b1f9fc890..7a8aba996 100644 --- a/doc/postgis.xml +++ b/doc/postgis.xml @@ -5016,6 +5016,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 9232d182d..5692dc050 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 e517b6f10..41498939b 100644 --- a/lwgeom/lwgeom_api.c +++ b/lwgeom/lwgeom_api.c @@ -8,6 +8,11 @@ #include "liblwgeom.h" #include "wktparse.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 @@ -427,14 +432,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)) @@ -442,11 +449,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; + } @@ -479,64 +516,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; } @@ -548,17 +630,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; } @@ -568,21 +640,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 @@ -593,6 +663,7 @@ getPoint_internal(const POINTARRAY *pa, int n) { int size; +#if PARANOIA_LEVEL > 0 if ( pa == NULL ) { lwerror("getPoint got NULL pointarray"); return NULL; @@ -602,6 +673,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 9ed6f2bd3..2e9a59cff 100644 --- a/regress/regress.sql +++ b/regress/regress.sql @@ -238,4 +238,9 @@ 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)')); + select '144', asewkt(linemerge('GEOMETRYCOLLECTION(LINESTRING(0 0, 1 1), LINESTRING(4 4, 1 1), LINESTRING(-5 -5, 0 0))'::geometry)); diff --git a/regress/regress_expected b/regress/regress_expected index 42e899c14..c98a3080b 100644 --- a/regress/regress_expected +++ b/regress/regress_expected @@ -143,4 +143,8 @@ 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) 144|LINESTRING(-5 -5,0 0,1 1,4 4)