From be428ac347665fc6da17b6c552c2e423a571842e Mon Sep 17 00:00:00 2001 From: Sandro Santilli Date: Tue, 5 Oct 2004 16:28:34 +0000 Subject: [PATCH] Added ZM dimensions flags knowledge. git-svn-id: http://svn.osgeo.org/postgis/trunk@929 b70326c6-7e19-0410-871a-916f4a2858ee --- lwgeom/liblwgeom.h | 62 ++-- lwgeom/lwcollection.c | 21 +- lwgeom/lwgeom_api.c | 395 +++++++++++++----------- lwgeom/lwgeom_box2dfloat4.c | 4 +- lwgeom/lwgeom_box3d.c | 4 +- lwgeom/lwgeom_chip.c | 4 +- lwgeom/lwgeom_functions_analytic.c | 42 ++- lwgeom/lwgeom_functions_basic.c | 477 +++++++++++++++++++++-------- lwgeom/lwgeom_geos.c | 30 +- lwgeom/lwgeom_gml.c | 22 +- lwgeom/lwgeom_inout.c | 4 +- lwgeom/lwgeom_ogc.c | 48 ++- lwgeom/lwgeom_spheroid.c | 15 +- lwgeom/lwgparse.c | 2 + lwgeom/lwline.c | 151 ++++----- lwgeom/lwmline.c | 5 +- lwgeom/lwmpoint.c | 3 +- lwgeom/lwmpoly.c | 5 +- lwgeom/lwpoint.c | 63 ++-- lwgeom/lwpoly.c | 50 +-- lwgeom/lwpostgis.sql.in | 13 +- lwgeom/wktparse.lex | 1 + lwgeom/wktparse.y | 1 + 23 files changed, 902 insertions(+), 520 deletions(-) diff --git a/lwgeom/liblwgeom.h b/lwgeom/liblwgeom.h index a689e6a44..58dd4af4e 100644 --- a/lwgeom/liblwgeom.h +++ b/lwgeom/liblwgeom.h @@ -3,6 +3,9 @@ //liblwgeom.h +#define DEBUG 1 +#define DEBUG_CALLS 1 + typedef void* (*lwallocator)(size_t size); typedef void* (*lwreallocator)(void *mem, size_t size); @@ -97,14 +100,15 @@ typedef struct } SPHEROID; -// POINT3D already defined in postgis.h // ALL LWGEOM structures will use POINT3D as an abstract point. // This means a 2d geometry will be stored as (x,y) in its serialized // form, but all functions will work on (x,y,0). This keeps all the // analysis functions simple. // NOTE: for GEOS integration, we'll probably set z=NaN // so look out - z might be NaN for 2d geometries! -typedef struct { double x,y,z; } POINT3D; +typedef struct { double x,y,z; } POINT3DZ; +typedef struct { double x,y,z; } POINT3D; // alias for POINT3DZ +typedef struct { double x,y,m; } POINT3DM; // type for 2d points. When you convert this to 3d, the @@ -134,7 +138,7 @@ typedef struct char *serialized_pointlist; // array of POINT 2D, 3D or 4D. // probably missaligned. // points to a double - char ndims; // 2=2d, 3=3d, 4=4d + unsigned char dims; // use TYPE_* macros to handle uint32 npoints; } POINTARRAY; @@ -237,18 +241,20 @@ extern POINT4D 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 -// NOTE: this will modify the point32d pointed to by 'point'. -extern void getPoint4d_p(const POINTARRAY *pa, int n, char *point); +// NOTE: this will modify the point4d pointed to by 'point'. +extern int getPoint4d_p(const POINTARRAY *pa, int n, POINT4D *point); // copies a point from the point array into the parameter point // will set point's z=0 (or NaN) if pa is 2d // NOTE: point is a real POINT3D *not* a pointer -extern POINT3D getPoint3d(const POINTARRAY *pa, int n); +extern POINT3DZ getPoint3dz(const POINTARRAY *pa, int n); +extern POINT3DM getPoint3dm(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 // NOTE: this will modify the point3d pointed to by 'point'. -extern void getPoint3d_p(const POINTARRAY *pa, int n, char *point); +extern int getPoint3dz_p(const POINTARRAY *pa, int n, POINT3DZ *point); +extern int getPoint3dm_p(const POINTARRAY *pa, int n, POINT3DM *point); // copies a point from the point array into the parameter point @@ -259,7 +265,7 @@ extern POINT2D getPoint2d(const POINTARRAY *pa, int n); // copies a point from the point array into the parameter point // z value (if present is not returned) // NOTE: this will modify the point2d pointed to by 'point'. -extern void getPoint2d_p(const POINTARRAY *pa, int n, char *point); +extern int getPoint2d_p(const POINTARRAY *pa, int n, POINT2D *point); // get a pointer to nth point of a POINTARRAY // You'll need to cast it to appropriate dimensioned point. @@ -272,9 +278,9 @@ extern char *getPoint(const POINTARRAY *pa, int n); // constructs a POINTARRAY. // NOTE: points is *not* copied, so be careful about modification (can be aligned/missaligned) -// NOTE: ndims is descriptive - it describes what type of data 'points' -// points to. No data conversion is done. -extern POINTARRAY *pointArray_construct(char *points, int ndims, uint32 npoints); +// NOTE: hasz and hasm are descriptive - it describes what type of data +// 'points' points to. No data conversion is done. +extern POINTARRAY *pointArray_construct(char *points, char hasz, char hasm, uint32 npoints); //calculate the bounding box of a set of points // returns a 3d box @@ -332,6 +338,7 @@ extern int pointArray_ptsize(const POINTARRAY *pa); #define TYPE_HASSRID(t) (((t)&0x40)) #define TYPE_NDIMS(t) ((((t)&0x20)>>5)+(((t)&0x10)>>4)+2) #define TYPE_GETTYPE(t) ((t)&0x0F) +#define TYPE_GETZM(t) (((t)&0x30)>>4) extern char lwgeom_hasBBOX(unsigned char type); // true iff B bit set extern int lwgeom_ndims(unsigned char type); // returns 2,3 or 4 @@ -339,8 +346,8 @@ extern int lwgeom_hasZ(unsigned char type); // has Z ? extern int lwgeom_hasM(unsigned char type); // has M ? extern int lwgeom_getType(unsigned char type); // returns the tttt value -extern unsigned char lwgeom_makeType(int ndims, char hasSRID, int type); -extern unsigned char lwgeom_makeType_full(int ndims, char hasSRID, int type, char hasBBOX); +extern unsigned char lwgeom_makeType(char hasZ, char hasM, char hasSRID, int type); +extern unsigned char lwgeom_makeType_full(char hasZ, char hasM, char hasSRID, int type, char hasBBOX); extern char lwgeom_hasSRID(unsigned char type); // true iff S bit is set extern char lwgeom_hasBBOX(unsigned char type); // true iff B bit set @@ -395,7 +402,7 @@ extern uint32 lwgeom_size_poly(const char *serialized_line); // construct a new point. point will NOT be copied // use SRID=-1 for unknown SRID (will have 8bit type's S = 0) -extern LWPOINT *lwpoint_construct(int ndims, int SRID, char wantbbox, POINTARRAY *point); +extern LWPOINT *lwpoint_construct(char hasZ, char hasM, int SRID, char wantbbox, POINTARRAY *point); // given the LWPOINT serialized form (or a pointer into a muli* one) // construct a proper LWPOINT. @@ -418,14 +425,16 @@ extern void lwpoint_serialize_buf(LWPOINT *point, char *buf, size_t *size); extern BOX3D *lwpoint_findbbox(LWPOINT *point); // convenience functions to hide the POINTARRAY -extern POINT2D lwpoint_getPoint2d(const LWPOINT *point); -extern POINT3D lwpoint_getPoint3d(const LWPOINT *point); +extern int lwpoint_getPoint2d_p(const LWPOINT *point, POINT2D *out); +extern int lwpoint_getPoint3dz_p(const LWPOINT *point, POINT3DZ *out); +extern int lwpoint_getPoint3dm_p(const LWPOINT *point, POINT3DM *out); +extern int lwpoint_getPoint4d_p(const LWPOINT *point, POINT4D *out); //-------------------------------------------------------- // construct a new LWLINE. points will *NOT* be copied // use SRID=-1 for unknown SRID (will have 8bit type's S = 0) -extern LWLINE *lwline_construct(int ndims, int SRID, char wantbbox, POINTARRAY *points); +extern LWLINE *lwline_construct(char hasz, char hasm, int SRID, char wantbbox, POINTARRAY *points); // given the LWGEOM serialized form (or a pointer into a muli* one) // construct a proper LWLINE. @@ -451,7 +460,7 @@ extern BOX3D *lwline_findbbox(LWLINE *line); // construct a new LWPOLY. arrays (points/points per ring) will NOT be copied // use SRID=-1 for unknown SRID (will have 8bit type's S = 0) -extern LWPOLY *lwpoly_construct(int ndims, int SRID, char wantbbox, int nrings, POINTARRAY **points); +extern LWPOLY *lwpoly_construct(char hasz, char hasm, int SRID, char wantbbox, int nrings, POINTARRAY **points); // given the LWPOLY serialized form (or a pointer into a muli* one) // construct a proper LWPOLY. @@ -541,7 +550,7 @@ extern int lwgeom_size_inspected(const LWGEOM_INSPECTED *inspected, int geom_num typedef struct { int SRID; - int ndims; + unsigned char dims; uint32 npoints; char **points; uint32 nlines; @@ -643,12 +652,12 @@ extern int lwgeom_getnumgeometries_inspected(LWGEOM_INSPECTED *inspected); // use SRID=-1 for unknown SRID (will have 8bit type's S = 0) // all subgeometries must have the same SRID // if you want to construct an inspected, call this then inspect the result... -extern char *lwgeom_construct(int SRID,int finalType,int ndims, int nsubgeometries, char **serialized_subs); +extern char *lwgeom_serialized_construct(int SRID, int finalType, char hasz, char hasm, int nsubgeometries, char **serialized_subs); // construct the empty geometry (GEOMETRYCOLLECTION(EMPTY)) -extern char *lwgeom_constructempty(int SRID,int ndims); -extern void lwgeom_constructempty_buf(int SRID, int ndims, char *buf, int *size); +extern char *lwgeom_constructempty(int SRID, char hasz, char hasm); +extern void lwgeom_constructempty_buf(int SRID, char hasz, char hasm, char *buf, int *size); int lwgeom_empty_length(int SRID); // get the SRID from the LWGEOM @@ -871,9 +880,10 @@ extern double lwgeom_polygon_perimeter(LWPOLY *poly); extern double lwgeom_polygon_perimeter2d(LWPOLY *poly); extern double lwgeom_pointarray_length2d(POINTARRAY *pts); extern double lwgeom_pointarray_length(POINTARRAY *pts); -extern void lwgeom_force2d_recursive(char *serialized, char *optr, int *retsize); -extern void lwgeom_force3d_recursive(char *serialized, char *optr, int *retsize); -extern void lwgeom_force4d_recursive(char *serialized, char *optr, int *retsize); +extern void lwgeom_force2d_recursive(char *serialized, char *optr, size_t *retsize); +extern void lwgeom_force3dz_recursive(char *serialized, char *optr, size_t *retsize); +extern void lwgeom_force3dm_recursive(char *serialized, char *optr, size_t *retsize); +extern void lwgeom_force4d_recursive(char *serialized, char *optr, size_t *retsize); extern double distance2d_pt_pt(POINT2D *p1, POINT2D *p2); extern double distance2d_pt_seg(POINT2D *p, POINT2D *A, POINT2D *B); extern double distance2d_seg_seg(POINT2D *A, POINT2D *B, POINT2D *C, POINT2D *D); @@ -937,7 +947,7 @@ extern LWLINE *lwline_clone(const LWLINE *lwgeom); extern LWPOLY *lwpoly_clone(const LWPOLY *lwgeom); extern LWCOLLECTION *lwcollection_clone(const LWCOLLECTION *lwgeom); -extern LWCOLLECTION *lwcollection_construct(int type, int ndims, uint32 SRID, char hasbbox, int ngeoms, LWGEOM **geoms); +extern LWCOLLECTION *lwcollection_construct(int type, char hasz, char hasm, uint32 SRID, char hasbbox, int ngeoms, LWGEOM **geoms); // Return a char string with ASCII versionf of type flags extern const char *lwgeom_typeflags(unsigned char type); diff --git a/lwgeom/lwcollection.c b/lwgeom/lwcollection.c index 43a06922e..cab581ea9 100644 --- a/lwgeom/lwcollection.c +++ b/lwgeom/lwcollection.c @@ -85,9 +85,15 @@ lwcollection_serialize_buf(LWCOLLECTION *coll, char *buf, size_t *retsize) char *loc; int i; +#ifdef DEBUG_CALLS + lwnotice("lwcollection_serialize_buf called (%d with %d elems)", + lwgeom_typename(TYPE_GETTYPE(coll->type)), coll->ngeoms); +#endif + hasSRID = (coll->SRID != -1); - buf[0] = (unsigned char) lwgeom_makeType_full(TYPE_NDIMS(coll->type), + buf[0] = (unsigned char) lwgeom_makeType_full( + TYPE_HASZ(coll->type), TYPE_HASM(coll->type), hasSRID, TYPE_GETTYPE(coll->type), TYPE_HASBBOX(coll->type)); loc = buf+1; @@ -121,6 +127,10 @@ lwcollection_serialize_buf(LWCOLLECTION *coll, char *buf, size_t *retsize) } if (retsize) *retsize = size; + +#ifdef DEBUG_CALLS + lwnotice("lwcollection_serialize_buf returning"); +#endif } int @@ -140,13 +150,13 @@ lwcollection_compute_bbox_p(LWCOLLECTION *col, BOX2DFLOAT4 *box) } LWCOLLECTION * -lwcollection_construct(int type, int ndims, uint32 SRID, char hasbbox, +lwcollection_construct(int type, char hasz, char hasm, uint32 SRID, char hasbbox, int ngeoms, LWGEOM **geoms) { LWCOLLECTION *ret; ret = lwalloc(sizeof(LWCOLLECTION)); - ret->type = lwgeom_makeType_full(ndims, (SRID!=-1), COLLECTIONTYPE, - hasbbox); + ret->type = lwgeom_makeType_full(hasz, hasm, (SRID!=-1), + type, hasbbox); ret->SRID = SRID; ret->ngeoms = ngeoms; ret->geoms = geoms; @@ -200,7 +210,8 @@ lwcollection_add(const LWCOLLECTION *to, uint32 where, const LWGEOM *what) geoms[i+1] = lwgeom_clone(to->geoms[i]); } - col = lwcollection_construct(COLLECTIONTYPE, TYPE_NDIMS(to->type), + col = lwcollection_construct(COLLECTIONTYPE, + TYPE_HASZ(to->type), TYPE_HASM(to->type), to->SRID, ( TYPE_HASBBOX(what->type) || TYPE_HASBBOX(to->type) ), to->ngeoms+1, geoms); diff --git a/lwgeom/lwgeom_api.c b/lwgeom/lwgeom_api.c index 700e34375..483f094af 100644 --- a/lwgeom/lwgeom_api.c +++ b/lwgeom/lwgeom_api.c @@ -9,7 +9,9 @@ // this will change to NaN when I figure out how to // get NaN in a platform-independent way -#define NO_Z_VALUE 0.0 +#define NO_VALUE 0.0 +#define NO_Z_VALUE NO_VALUE +#define NO_M_VALUE NO_VALUE //#define DEBUG 1 //#define DEBUG_EXPLODED 1 @@ -429,117 +431,136 @@ getbox2d_internal(char *serialized_form) POINT4D getPoint4d(const POINTARRAY *pa, int n) { - POINT4D 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 ); - if (pa->ndims >2) - memcpy(&result.z, &pa->serialized_pointlist[size*n + sizeof(double)*2],sizeof(double) ); - else - result.z = NO_Z_VALUE; - if (pa->ndims >3) - memcpy(&result.m, &pa->serialized_pointlist[size*n + sizeof(double)*3],sizeof(double) ); - else - result.m = NO_Z_VALUE; - - return result; + POINT4D result; + getPoint4d_p(pa, n, &result); + return result; } // 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 // NOTE: this will modify the point4d pointed to by 'point'. -void -getPoint4d_p(const POINTARRAY *pa, int n, char *point) +int +getPoint4d_p(const POINTARRAY *pa, int n, POINT4D *point) { - int size; + int size; + POINT4D *pt; + + if ( ! pa ) return 0; - if ( (n<0) || (n>=pa->npoints)) - { - return ; //error - } + if ( (n<0) || (n>=pa->npoints)) + { + lwerror("getPoint4d_p: point offset out of range"); + return 0; //error + } + + size = pointArray_ptsize(pa); - size = pointArray_ptsize(pa); + pt = (POINT4D *)getPoint(pa, n); - // this does x,y - memcpy(point, &pa->serialized_pointlist[size*n],sizeof(double)*2 ); - if (pa->ndims >2) - memcpy(point+16, &pa->serialized_pointlist[size*n + sizeof(double)*2],sizeof(double) ); - else - { - double bad=NO_Z_VALUE; - memcpy(point+16, &bad,sizeof(double) ); - //point->z = NO_Z_VALUE; - } + // Initialize point + point->x = pt->x; + point->y = pt->y; + point->z = NO_Z_VALUE; + point->m = NO_M_VALUE; - if (pa->ndims >3) - memcpy(point+24, &pa->serialized_pointlist[size*n + sizeof(double)*3],sizeof(double) ); - else - { - double bad=NO_Z_VALUE; - memcpy(point+24, &bad,sizeof(double) ); - //point->z = NO_Z_VALUE; - } + if (TYPE_HASZ(pa->dims)) + { + point->z = pt->z; + if (TYPE_HASM(pa->dims)) + { + point->m = pt->m; + } + } + else if (TYPE_HASM(pa->dims)) + { + point->m = pt->z; + } + + return 1; } // copies a point from the point array into the parameter point // will set point's z=0 (or NaN) if pa is 2d -// NOTE: point is a real POINT3D *not* a pointer -POINT3D -getPoint3d(const POINTARRAY *pa, int n) +// NOTE: point is a real POINT3DZ *not* a pointer +POINT3DZ +getPoint3dz(const POINTARRAY *pa, int n) +{ + POINT3DZ result; + getPoint3dz_p(pa, n, &result); + return result; +} + +// copies a point from the point array into the parameter point +// will set point's z=0 (or NaN) if pa is 2d +// NOTE: point is a real POINT3DZ *not* a pointer +POINT3DM +getPoint3dm(const POINTARRAY *pa, int n) +{ + POINT3DM result; + getPoint3dm_p(pa, n, &result); + return result; +} + +// copies a point from the point array into the parameter point +// will set point's z=NO_Z_VALUE if pa is 2d +// NOTE: this will modify the point3dz pointed to by 'point'. +int +getPoint3dz_p(const POINTARRAY *pa, int n, POINT3DZ *op) { - POINT3D result; int size; + POINT4D *ip; + + if ( ! pa ) return 0; + +#ifdef 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)) { - return result; //error + lwnotice("%d out of numpoint range (%d)", n, pa->npoints); + return 0; //error } size = pointArray_ptsize(pa); - // this does x,y - memcpy(&result.x, &pa->serialized_pointlist[size*n],sizeof(double)*2 ); - if (pa->ndims >2) - memcpy(&result.z, &pa->serialized_pointlist[size*n + sizeof(double)*2],sizeof(double) ); - else - result.z = NO_Z_VALUE; - return result; +#ifdef DEBUG + lwnotice("getPoint3dz_p: point size: %d", size); +#endif + + ip = (POINT4D *)getPoint(pa, n); + op->x = ip->x; + op->y = ip->y; + if ( TYPE_HASZ(pa->dims) ) op->z = ip->z; + else op->z = NO_Z_VALUE; + + return 1; } // copies a point from the point array into the parameter point -// will set point's z=NO_Z_VALUE if pa is 2d -// NOTE: this will modify the point3d pointed to by 'point'. -// we use a char* instead of a POINT3D because we want to use this function -// for serialization/de-serialization -void -getPoint3d_p(const POINTARRAY *pa, int n, char *point) +// will set point's m=NO_Z_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; - POINT3D *op, *ip; + POINT4D *ip; - op = (POINT3D *)point; + if ( ! pa ) return 0; #ifdef DEBUG - lwnotice("getPoint3d_p called on array of %d-dimensions / %u pts", - pa->ndims, pa->npoints); - if ( pa->npoints > 1000 ) lwerror("More then 1000 points in pointarray ??"); + 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)) { - lwnotice("%d out of numpoint range (%d)", n, pa->npoints); - return ; //error + lwerror("%d out of numpoint range (%d)", n, pa->npoints); + return 0; //error } size = pointArray_ptsize(pa); @@ -548,12 +569,21 @@ getPoint3d_p(const POINTARRAY *pa, int n, char *point) lwnotice("getPoint3d_p: point size: %d", size); #endif - ip = (POINT3D *)getPoint(pa, n); + ip = (POINT4D *)getPoint(pa, n); op->x = ip->x; op->y = ip->y; - if (pa->ndims >2) op->z = ip->z; - else op->z = NO_Z_VALUE; - return; + op->m = NO_M_VALUE; + + if ( TYPE_HASM(pa->dims) ) + { + if ( TYPE_HASZ(pa->dims) ) + { + op->m = ip->m; + } + else op->m = ip->z; + } + + return 1; } @@ -581,22 +611,24 @@ getPoint2d(const POINTARRAY *pa, int n) // copies a point from the point array into the parameter point // z value (if present is not returned) // NOTE: this will modify the point2d pointed to by 'point'. -// we use a char* instead of a POINT2D because we want to use this function -// for serialization/de-serialization -void -getPoint2d_p(const POINTARRAY *pa, int n, char *point) +int +getPoint2d_p(const POINTARRAY *pa, int n, POINT2D *point) { int size; + if ( ! pa ) return 0; + if ( (n<0) || (n>=pa->npoints)) { - return; //error + lwerror("getPoint2d_p: point offset out of range"); + return 0; //error } size = pointArray_ptsize(pa); // this does x,y memcpy(point, &pa->serialized_pointlist[size*n],sizeof(double)*2 ); + return 1; } // get a pointer to nth point of a POINTARRAY @@ -630,15 +662,14 @@ getPoint(const POINTARRAY *pa, int n) // NOTE: points is *not* copied, so be careful about modification (can be aligned/missaligned) // NOTE: ndims is descriptive - it describes what type of data 'points' // points to. No data conversion is done. -POINTARRAY *pointArray_construct(char *points, int ndims, uint32 npoints) +POINTARRAY * +pointArray_construct(char *points, char hasz, char hasm, uint32 npoints) { POINTARRAY *pa; pa = (POINTARRAY*)lwalloc(sizeof(POINTARRAY)); - if (ndims>4) - lwerror("pointArray_construct:: called with dims = %i", (int) ndims); - - pa->ndims = ndims; + pa->dims = 0; + TYPE_SETZM(pa->dims, hasz, hasm); pa->npoints = npoints; pa->serialized_pointlist = points; @@ -648,11 +679,12 @@ POINTARRAY *pointArray_construct(char *points, int ndims, uint32 npoints) // calculate the bounding box of a set of points // returns a lwalloced BOX3D, or NULL on empty array. // zmin/zmax values are set to NO_Z_VALUE if not available. -BOX3D *pointArray_bbox(const POINTARRAY *pa) +BOX3D * +pointArray_bbox(const POINTARRAY *pa) { int t; BOX3D *result; - POINT3D *pt; + POINT3DZ pt; int npoints = pa->npoints; #ifdef DEBUG @@ -670,31 +702,27 @@ BOX3D *pointArray_bbox(const POINTARRAY *pa) result = (BOX3D*)lwalloc(sizeof(BOX3D)); - if ( npoints != pa->npoints) lwerror("Messed up at %s:%d", __FILE__, __LINE__); - if ( ! result ) { lwnotice("Out of virtual memory"); return NULL; } - //getPoint3d_p(pa, 0, (char*)pt); - pt = (POINT3D *)getPoint(pa, 0); + getPoint3dz_p(pa, 0, &pt); - if ( npoints != pa->npoints) lwerror("Messed up at %s:%d", __FILE__, __LINE__); #ifdef DEBUG lwnotice("pointArray_bbox: got point 0"); #endif - result->xmin = pt->x; - result->xmax = pt->x; - result->ymin = pt->y; - result->ymax = pt->y; + result->xmin = pt.x; + result->xmax = pt.x; + result->ymin = pt.y; + result->ymax = pt.y; - if ( pa->ndims > 2 ) { - result->zmin = pt->z; - result->zmax = pt->z; + if ( TYPE_HASZ(pa->dims) ) { + result->zmin = pt.z; + result->zmax = pt.z; } else { result->zmin = NO_Z_VALUE; result->zmax = NO_Z_VALUE; @@ -705,16 +733,15 @@ BOX3D *pointArray_bbox(const POINTARRAY *pa) #endif for (t=1;tnpoints;t++) { - //getPoint3d_p(pa,t,(char*)&pt); - pt = (POINT3D *)getPoint(pa, t); - if (pt->x < result->xmin) result->xmin = pt->x; - if (pt->y < result->ymin) result->ymin = pt->y; - if (pt->x > result->xmax) result->xmax = pt->x; - if (pt->y > result->ymax) result->ymax = pt->y; + getPoint3dz_p(pa,t,&pt); + if (pt.x < result->xmin) result->xmin = pt.x; + if (pt.y < result->ymin) result->ymin = pt.y; + if (pt.x > result->xmax) result->xmax = pt.x; + if (pt.y > result->ymax) result->ymax = pt.y; - if ( pa->ndims > 2 ) { - if (pt->z > result->zmax) result->zmax = pt->z; - if (pt->z < result->zmax) result->zmax = pt->z; + if ( TYPE_HASZ(pa->dims) ) { + if (pt.z > result->zmax) result->zmax = pt.z; + if (pt.z < result->zmax) result->zmax = pt.z; } } @@ -760,13 +787,7 @@ ptarray_compute_bbox_p(const POINTARRAY *pa, BOX2DFLOAT4 *result) int pointArray_ptsize(const POINTARRAY *pa) { - if ( pa->ndims < 2 || pa->ndims > 4 ) - { - lwerror("pointArray_ptsize:: ndims isnt 2,3, or 4"); - return 0; // never get here - } - - return sizeof(double)*pa->ndims; + return sizeof(double)*TYPE_NDIMS(pa->dims); } @@ -785,7 +806,7 @@ lwgeom_hasSRID(unsigned char type) int lwgeom_ndims(unsigned char type) { - return TYPE_NDIMS(type); + return TYPE_NDIMS(type); } // has M ? @@ -809,33 +830,31 @@ int lwgeom_getType(unsigned char type) //construct a type (hasBOX=false) -unsigned char lwgeom_makeType(int ndims, char hasSRID, int type) +unsigned char +lwgeom_makeType(char hasz, char hasm, char hasSRID, int type) { - return lwgeom_makeType_full(ndims, hasSRID, type, 0); + return lwgeom_makeType_full(hasz, hasm, hasSRID, type, 0); } /* * Construct a type * TODO: needs to be expanded to accept explicit MZ type */ -unsigned char lwgeom_makeType_full(int ndims, char hasSRID, int type, char hasBBOX) +unsigned char +lwgeom_makeType_full(char hasz, char hasm, char hasSRID, int type, char hasBBOX) { - unsigned char result = type; + unsigned char result = (char)type; - if (ndims == 3) - TYPE_SETZM(result, 1, 0); - if (ndims == 4) - TYPE_SETZM(result, 1, 1); - if (hasSRID) - TYPE_SETHASSRID(result, 1); - if (hasBBOX) - TYPE_SETHASBBOX(result, 1); + TYPE_SETZM(result, hasz, hasm); + TYPE_SETHASSRID(result, hasSRID); + TYPE_SETHASBBOX(result, hasBBOX); return result; } //returns true if there's a bbox in this LWGEOM (B bit set) -char lwgeom_hasBBOX(unsigned char type) +char +lwgeom_hasBBOX(unsigned char type) { return TYPE_HASBBOX(type); } @@ -965,14 +984,8 @@ lwgeom_inspect(const char *serialized_form) type = lwgeom_getType( (unsigned char) serialized_form[0]); - loc = serialized_form+1; - if (lwgeom_hasBBOX((unsigned char) serialized_form[0])) - { - loc += sizeof(BOX2DFLOAT4); - } - if ( (type==POINTTYPE) || (type==LINETYPE) || (type==POLYGONTYPE) ) { if (lwgeom_hasSRID((unsigned char) serialized_form[0]) ) @@ -989,6 +1002,11 @@ lwgeom_inspect(const char *serialized_form) // its a GeometryCollection or multi* geometry + if (lwgeom_hasBBOX((unsigned char) serialized_form[0])) + { + loc += sizeof(BOX2DFLOAT4); + } + if (lwgeom_hasSRID((unsigned char) serialized_form[0]) ) { result->SRID= get_int32(loc); @@ -1265,7 +1283,8 @@ int lwgeom_getnumgeometries_inspected(LWGEOM_INSPECTED *inspected) // use SRID=-1 for unknown SRID (will have 8bit type's S = 0) // all subgeometries must have the same SRID // if you want to construct an inspected, call this then inspect the result... -extern char *lwgeom_construct(int SRID,int finalType,int ndims, int nsubgeometries, char **serialized_subs) +char * +lwgeom_serialized_construct(int SRID, int finalType, char hasz, char hasm, int nsubgeometries, char **serialized_subs) { uint32 *lengths; int t; @@ -1276,7 +1295,7 @@ extern char *lwgeom_construct(int SRID,int finalType,int ndims, int nsubgeometri char *loc; if (nsubgeometries == 0) - return lwgeom_constructempty(SRID,ndims); + return lwgeom_constructempty(SRID, hasz, hasm); lengths = lwalloc(sizeof(int32) * nsubgeometries); @@ -1338,7 +1357,7 @@ extern char *lwgeom_construct(int SRID,int finalType,int ndims, int nsubgeometri total_length +=4 ; // nsubgeometries result = lwalloc(total_length); - result[0] = (unsigned char) lwgeom_makeType( ndims, SRID != -1, type); + result[0] = (unsigned char) lwgeom_makeType(hasz, hasm, SRID != -1, type); if (SRID != -1) { memcpy(&result[1],&SRID,4); @@ -1363,7 +1382,8 @@ extern char *lwgeom_construct(int SRID,int finalType,int ndims, int nsubgeometri // construct the empty geometry (GEOMETRYCOLLECTION(EMPTY)) //returns serialized form -char *lwgeom_constructempty(int SRID,int ndims) +char * +lwgeom_constructempty(int SRID, char hasz, char hasm) { int size = 0; char *result; @@ -1377,7 +1397,7 @@ char *lwgeom_constructempty(int SRID,int ndims) result = lwalloc(size); - result[0] =(unsigned char) lwgeom_makeType( ndims, SRID != -1, COLLECTIONTYPE); + result[0] = lwgeom_makeType(hasz, hasm, SRID != -1, COLLECTIONTYPE); if (SRID != -1) { memcpy(&result[1],&SRID,4); @@ -1401,11 +1421,11 @@ lwgeom_empty_length(int SRID) // construct the empty geometry (GEOMETRYCOLLECTION(EMPTY)) // writing it into the provided buffer. void -lwgeom_constructempty_buf(int SRID, int ndims, char *buf, int *retsize) +lwgeom_constructempty_buf(int SRID, char hasz, char hasm, char *buf, int *retsize) { int ngeoms = 0; - buf[0] =(unsigned char) lwgeom_makeType( ndims, SRID != -1, COLLECTIONTYPE); + buf[0] =(unsigned char) lwgeom_makeType( hasz, hasm, SRID != -1, COLLECTIONTYPE); if (SRID != -1) { memcpy(&buf[1],&SRID,4); @@ -1500,7 +1520,7 @@ lwgeom_size(const char *serialized_form) } - ngeoms = get_uint32(loc); + ngeoms = get_uint32(loc); loc +=4; result += 4; // numgeoms @@ -1723,30 +1743,31 @@ void pfree_POINTARRAY(POINTARRAY *pa) void printPA(POINTARRAY *pa) { int t; - POINT2D pt2; - POINT3D pt3; - POINT4D pt4; + POINT4D *pt; + char *mflag; + + if ( TYPE_HASM(pa->dims) ) mflag = "M"; + else mflag = ""; - lwnotice(" POINTARRAY{"); - lwnotice(" ndims =%i, ptsize=%i", (int) pa->ndims,pointArray_ptsize(pa)); + lwnotice(" POINTARRAY%s{", mflag); + lwnotice(" ndims=%i, ptsize=%i", + TYPE_NDIMS(pa->dims), pointArray_ptsize(pa)); lwnotice(" npoints = %i", pa->npoints); for (t =0; tnpoints;t++) { - if (pa->ndims == 2) + pt = (POINT4D *)getPoint(pa,t); + if (TYPE_NDIMS(pa->dims) == 2) { - pt2 = getPoint2d(pa,t); - lwnotice(" %i : %lf,%lf",t,pt2.x,pt2.y); + lwnotice(" %i : %lf,%lf",t,pt->x,pt->y); } - if (pa->ndims == 3) + if (TYPE_NDIMS(pa->dims) == 3) { - pt3 = getPoint3d(pa,t); - lwnotice(" %i : %lf,%lf,%lf",t,pt3.x,pt3.y,pt3.z); + lwnotice(" %i : %lf,%lf,%lf",t,pt->x,pt->y,pt->z); } - if (pa->ndims == 4) + if (TYPE_NDIMS(pa->dims) == 4) { - pt4 = getPoint4d(pa,t); - lwnotice(" %i : %lf,%lf,%lf,%lf",t,pt3.x,pt4.y,pt4.z,pt4.m); + lwnotice(" %i : %lf,%lf,%lf,%lf",t,pt->x,pt->y,pt->z,pt->m); } } @@ -1850,7 +1871,8 @@ int lwgeom_getSRID(PG_LWGEOM *lwgeom) // Set the SRID of a LWGEOM // Returns a newly allocated LWGEOM object. // Allocation will be done using the lwalloc. -PG_LWGEOM *lwgeom_setSRID(PG_LWGEOM *lwgeom, int32 newSRID) +PG_LWGEOM * +lwgeom_setSRID(PG_LWGEOM *lwgeom, int32 newSRID) { unsigned char type = lwgeom->type; int bbox_offset=0; //0=no bbox, otherwise sizeof(BOX2DFLOAT4) @@ -1875,7 +1897,9 @@ PG_LWGEOM *lwgeom_setSRID(PG_LWGEOM *lwgeom, int32 newSRID) len_new = len + 4;//+4 for SRID result = lwalloc(len_new); memcpy(result, &len_new, 4); // size copy in - result->type = lwgeom_makeType_full(lwgeom_ndims(type), 1, lwgeom_getType(type),lwgeom_hasBBOX(type)); + result->type = lwgeom_makeType_full( + TYPE_HASZ(type), TYPE_HASM(type), + 1, lwgeom_getType(type),lwgeom_hasBBOX(type)); loc_new = result->data; loc_old = lwgeom->data; @@ -1943,7 +1967,8 @@ PG_LWGEOM_construct(char *ser, int SRID, int wantbbox) result = lwalloc(size); result->size = size; - result->type = lwgeom_makeType_full(lwgeom_ndims(ser[0]), + result->type = lwgeom_makeType_full( + TYPE_HASZ(ser[0]), TYPE_HASM(ser[0]), wantsrid, lwgeom_getType(ser[0]), wantbbox); optr = result->data; if ( wantbbox ) @@ -2009,14 +2034,14 @@ lwnotice("lwgeom_explode: serialized inspected"); lwfree(result->lines); lwfree(result->polys); result->SRID = -1; - result->ndims = 0; + result->dims = inspected->type; pfree_inspected(inspected); //lwnotice("lwgeom_explode: no geometries"); return result; } result->SRID = lwgeom_getsrid(serialized); - result->ndims = lwgeom_ndims(serialized[0]); + result->dims = inspected->type; // will use ZM only for (i=0; ingeometries; i++) { @@ -2150,8 +2175,18 @@ lwexploded_sum(LWGEOM_EXPLODED *exp1, LWGEOM_EXPLODED *exp2) LWGEOM_EXPLODED *expcoll; char *loc; - if ( exp1->ndims != exp2->ndims ) return NULL; - if ( exp1->SRID != exp2->SRID ) return NULL; + if ( TYPE_GETZM(exp1->dims) != TYPE_GETZM(exp2->dims) ) + { + lwerror("lwexploded_sum: can't sum mixed DIMS geoms (%d/%d)", + TYPE_GETZM(exp1->dims), TYPE_GETZM(exp2->dims)); + return NULL; + } + if ( exp1->SRID != exp2->SRID ) + { + lwerror("lwexploded_sum: can't sum mixed SRID geoms (%d/%d)", + exp1->SRID, exp2->SRID); + return NULL; + } expcoll = lwalloc(sizeof(LWGEOM_EXPLODED)); @@ -2200,7 +2235,7 @@ lwexploded_sum(LWGEOM_EXPLODED *exp1, LWGEOM_EXPLODED *exp2) } } - expcoll->ndims = exp1->ndims; + expcoll->dims = exp1->dims; expcoll->SRID = exp1->SRID; return expcoll; @@ -2248,7 +2283,8 @@ lwexploded_serialize_buf(LWGEOM_EXPLODED *exploded, int wantbbox, if ( ngeoms == 0 ) { - lwgeom_constructempty_buf(exploded->SRID, exploded->ndims, + lwgeom_constructempty_buf(exploded->SRID, + TYPE_HASZ(exploded->dims), TYPE_HASM(exploded->dims), buf, retsize); return; } @@ -2353,8 +2389,9 @@ lwexploded_serialize_buf(LWGEOM_EXPLODED *exploded, int wantbbox, if ( exploded->npoints > 1 ) { - loc[0] = lwgeom_makeType_full(exploded->ndims, 0, - MULTIPOINTTYPE, 0); + loc[0] = lwgeom_makeType_full( + TYPE_HASZ(exploded->dims), TYPE_HASM(exploded->dims), + 0, MULTIPOINTTYPE, 0); loc++; memcpy(loc, &exploded->npoints, 4); // numpoints loc += 4; @@ -2372,8 +2409,10 @@ lwexploded_serialize_buf(LWGEOM_EXPLODED *exploded, int wantbbox, if ( exploded->nlines > 1 ) { - loc[0] = lwgeom_makeType_full(exploded->ndims, 0, - MULTILINETYPE, 0); + loc[0] = lwgeom_makeType_full( + TYPE_HASZ(exploded->dims), + TYPE_HASM(exploded->dims), + 0, MULTILINETYPE, 0); loc++; memcpy(loc, &exploded->nlines, 4); // numlines loc += 4; @@ -2397,8 +2436,10 @@ lwexploded_serialize_buf(LWGEOM_EXPLODED *exploded, int wantbbox, if ( exploded->npolys > 1 ) { - loc[0] = lwgeom_makeType_full(exploded->ndims, 0, - MULTIPOLYGONTYPE, 0); + loc[0] = lwgeom_makeType_full( + TYPE_HASZ(exploded->dims), + TYPE_HASM(exploded->dims), + 0, MULTIPOLYGONTYPE, 0); loc++; memcpy(loc, &exploded->npolys, 4); // numpolys loc += 4; @@ -2424,7 +2465,9 @@ lwexploded_serialize_buf(LWGEOM_EXPLODED *exploded, int wantbbox, if (retsize) *retsize = (loc-buf); // Ok. now we need to add type, SRID and bbox - buf[0] = lwgeom_makeType_full(exploded->ndims, + buf[0] = lwgeom_makeType_full( + TYPE_HASZ(exploded->dims), + TYPE_HASM(exploded->dims), (exploded->SRID!=-1), outtype, wantbbox); loc = buf+1; diff --git a/lwgeom/lwgeom_box2dfloat4.c b/lwgeom/lwgeom_box2dfloat4.c index a395e8b58..347cb2e92 100644 --- a/lwgeom/lwgeom_box2dfloat4.c +++ b/lwgeom/lwgeom_box2dfloat4.c @@ -430,11 +430,11 @@ Datum BOX2DFLOAT4_to_LWGEOM(PG_FUNCTION_ARGS) // Construct point array pa[0] = palloc(sizeof(POINTARRAY)); pa[0]->serialized_pointlist = (char *)pts; - pa[0]->ndims = 2; + TYPE_SETZM(pa[0]->dims, 0, 0); pa[0]->npoints = 5; // Construct polygon - poly = lwpoly_construct(2, -1, wantbbox, 1, pa); + poly = lwpoly_construct(0, 0, -1, wantbbox, 1, pa); // Serialize polygon ser = lwpoly_serialize(poly); diff --git a/lwgeom/lwgeom_box3d.c b/lwgeom/lwgeom_box3d.c index 496bf7bc7..1f735c600 100644 --- a/lwgeom/lwgeom_box3d.c +++ b/lwgeom/lwgeom_box3d.c @@ -176,11 +176,11 @@ Datum BOX3D_to_LWGEOM(PG_FUNCTION_ARGS) // Construct point array pa[0] = palloc(sizeof(POINTARRAY)); pa[0]->serialized_pointlist = (char *)pts; - pa[0]->ndims = 2; + TYPE_SETZM(pa[0]->dims, 0, 0); pa[0]->npoints = 5; // Construct polygon - poly = lwpoly_construct(2, -1, wantbbox, 1, pa); + poly = lwpoly_construct(0, 0, -1, wantbbox, 1, pa); // Serialize polygon ser = lwpoly_serialize(poly); diff --git a/lwgeom/lwgeom_chip.c b/lwgeom/lwgeom_chip.c index 2af28c797..82c147555 100644 --- a/lwgeom/lwgeom_chip.c +++ b/lwgeom/lwgeom_chip.c @@ -176,11 +176,11 @@ Datum CHIP_to_LWGEOM(PG_FUNCTION_ARGS) // Construct point array pa[0] = palloc(sizeof(POINTARRAY)); pa[0]->serialized_pointlist = (char *)pts; - pa[0]->ndims = 2; + TYPE_SETZM(pa[0]->dims, 0, 0); pa[0]->npoints = 5; // Construct polygon - poly = lwpoly_construct(2, chip->SRID, wantbbox, 1, pa); + poly = lwpoly_construct(0, 0, chip->SRID, wantbbox, 1, pa); // Serialize polygon ser = lwpoly_serialize(poly); diff --git a/lwgeom/lwgeom_functions_analytic.c b/lwgeom/lwgeom_functions_analytic.c index 36fd5d757..af7ceb052 100644 --- a/lwgeom/lwgeom_functions_analytic.c +++ b/lwgeom/lwgeom_functions_analytic.c @@ -11,7 +11,6 @@ * --strk@keybit.net; ***********************************************************************/ -#define SAMEPOINT(a,b) ((a)->x==(b)->x&&(a)->y==(b)->y&&(a)->z==(b)->z) #define VERBOSE 0 #if VERBOSE > 0 @@ -98,7 +97,7 @@ DP_simplify2d(POINTARRAY *inpts, double epsilon) int p1, split; double dist; POINTARRAY *outpts; - int ptsize = sizeof(double)*inpts->ndims; + int ptsize = pointArray_ptsize(inpts); p1 = 0; stack[++sp] = inpts->npoints-1; @@ -109,7 +108,7 @@ DP_simplify2d(POINTARRAY *inpts, double epsilon) // allocate space for output POINTARRAY outpts = palloc(sizeof(POINTARRAY)); - outpts->ndims = inpts->ndims; + outpts->dims = inpts->dims; outpts->npoints=1; outpts->serialized_pointlist = (char *)palloc(ptsize*inpts->npoints); memcpy(getPoint(outpts, 0), getPoint(inpts, 0), ptsize); @@ -176,7 +175,10 @@ simplify2d_lwline(LWLINE *iline, double dist) ipts = iline->points; opts = DP_simplify2d(ipts, dist); - oline = lwline_construct(ipts->ndims, iline->SRID, + oline = lwline_construct( + TYPE_HASZ(ipts->dims), + TYPE_HASM(ipts->dims), + iline->SRID, TYPE_HASBBOX(iline->type), opts); return oline; @@ -378,13 +380,17 @@ Datum LWGEOM_line_interpolate_point(PG_FUNCTION_ARGS) if ( distance == 0.0 || distance == 1.0 ) { if ( distance == 0.0 ) - getPoint4d_p(ipa, 0, (char *)&pt); + getPoint4d_p(ipa, 0, &pt); else - getPoint4d_p(ipa, ipa->npoints-1, (char *)&pt); + getPoint4d_p(ipa, ipa->npoints-1, &pt); opa = pointArray_construct((char *)&pt, - TYPE_NDIMS(line->type), 1); - point = lwpoint_construct(TYPE_NDIMS(line->type), + TYPE_HASZ(line->type), + TYPE_HASM(line->type), + 1); + point = lwpoint_construct( + TYPE_HASZ(line->type), + TYPE_HASM(line->type), line->SRID, 0, opa); srl = lwpoint_serialize(point); pfree_point(point); @@ -415,8 +421,12 @@ Datum LWGEOM_line_interpolate_point(PG_FUNCTION_ARGS) pt.z = 0; pt.m = 0; opa = pointArray_construct((char *)&pt, - TYPE_NDIMS(line->type), 1); - point = lwpoint_construct(TYPE_NDIMS(line->type), + TYPE_HASZ(line->type), + TYPE_HASM(line->type), + 1); + point = lwpoint_construct( + TYPE_HASZ(line->type), + TYPE_HASM(line->type), line->SRID, 0, opa); srl = lwpoint_serialize(point); pfree_point(point); @@ -427,9 +437,15 @@ Datum LWGEOM_line_interpolate_point(PG_FUNCTION_ARGS) /* Return the last point on the line. This shouldn't happen, but * could if there's some floating point rounding errors. */ - getPoint4d_p(ipa, ipa->npoints-1, (char *)&pt); - opa = pointArray_construct((char *)&pt, TYPE_NDIMS(line->type), 1); - point = lwpoint_construct(TYPE_NDIMS(line->type), line->SRID, 0, opa); + getPoint4d_p(ipa, ipa->npoints-1, &pt); + opa = pointArray_construct((char *)&pt, + TYPE_HASZ(line->type), + TYPE_HASM(line->type), + 1); + point = lwpoint_construct( + TYPE_HASZ(line->type), + TYPE_HASM(line->type), + line->SRID, 0, opa); srl = lwpoint_serialize(point); pfree_point(point); PG_RETURN_POINTER(PG_LWGEOM_construct(srl, line->SRID, 0)); diff --git a/lwgeom/lwgeom_functions_basic.c b/lwgeom/lwgeom_functions_basic.c index a0a80799b..a8514fd34 100644 --- a/lwgeom/lwgeom_functions_basic.c +++ b/lwgeom/lwgeom_functions_basic.c @@ -29,7 +29,8 @@ Datum LWGEOM_length_linestring(PG_FUNCTION_ARGS); Datum LWGEOM_perimeter2d_poly(PG_FUNCTION_ARGS); Datum LWGEOM_perimeter_poly(PG_FUNCTION_ARGS); Datum LWGEOM_force_2d(PG_FUNCTION_ARGS); -Datum LWGEOM_force_3d(PG_FUNCTION_ARGS); +Datum LWGEOM_force_3dm(PG_FUNCTION_ARGS); +Datum LWGEOM_force_3dz(PG_FUNCTION_ARGS); Datum LWGEOM_force_4d(PG_FUNCTION_ARGS); Datum LWGEOM_force_collection(PG_FUNCTION_ARGS); Datum LWGEOM_force_multi(PG_FUNCTION_ARGS); @@ -528,7 +529,8 @@ double lwgeom_pointarray_length2d(POINTARRAY *pts) } //find the 3d/2d length of the given POINTARRAY (depending on its dimensions) -double lwgeom_pointarray_length(POINTARRAY *pts) +double +lwgeom_pointarray_length(POINTARRAY *pts) { double dist = 0.0; int i; @@ -536,12 +538,12 @@ double lwgeom_pointarray_length(POINTARRAY *pts) if ( pts->npoints < 2 ) return 0.0; // compute 2d length if 3d is not available - if ( pts->ndims < 3 ) return lwgeom_pointarray_length2d(pts); + if ( ! TYPE_HASZ(pts->dims) ) return lwgeom_pointarray_length2d(pts); for (i=0; inpoints-1;i++) { - POINT3D *frm = (POINT3D *)getPoint(pts, i); - POINT3D *to = (POINT3D *)getPoint(pts, i+1); + POINT3DZ *frm = (POINT3DZ *)getPoint(pts, i); + POINT3DZ *to = (POINT3DZ *)getPoint(pts, i+1); dist += sqrt( ( (frm->x - to->x)*(frm->x - to->x) ) + ((frm->y - to->y)*(frm->y - to->y) ) + ((frm->z - to->z)*(frm->z - to->z) ) ); @@ -839,14 +841,17 @@ lwgeom_translate_ptarray(POINTARRAY *pa, double xoff, double yoff, double zoff) { int i; - if ( pa->ndims > 2 ) { + if ( TYPE_HASZ(pa->dims) ) + { for (i=0; inpoints; i++) { - POINT3D *p = (POINT3D *)getPoint(pa, i); + POINT3DZ *p = (POINT3DZ *)getPoint(pa, i); p->x += xoff; p->y += yoff; p->z += zoff; } - } else { + } + else + { for (i=0; inpoints; i++) { POINT2D *p = (POINT2D *)getPoint(pa, i); p->x += xoff; @@ -1227,7 +1232,7 @@ Datum LWGEOM_perimeter2d_poly(PG_FUNCTION_ARGS) * Return number bytes written in given int pointer. */ void -lwgeom_force2d_recursive(char *serialized, char *optr, int *retsize) +lwgeom_force2d_recursive(char *serialized, char *optr, size_t *retsize) { LWGEOM_INSPECTED *inspected; int i; @@ -1287,7 +1292,7 @@ elog(NOTICE, "lwgeom_force2d_recursive: it's a collection (type:%d)", type); #endif // Add type - *optr = lwgeom_makeType_full(2, lwgeom_hasSRID(serialized[0]), + *optr = lwgeom_makeType_full(0, 0, lwgeom_hasSRID(serialized[0]), type, lwgeom_hasBBOX(serialized[0])); optr++; totsize++; @@ -1338,14 +1343,14 @@ elog(NOTICE, " elem %d size: %d (tot: %d)", i, size, totsize); } /* - * Write to already allocated memory 'optr' a 3d version of + * Write to already allocated memory 'optr' a 3dz version of * the given serialized form. * Higher dimensions in input geometry are discarder. * If the given version is 2d Z is set to 0. * Return number bytes written in given int pointer. */ void -lwgeom_force3d_recursive(char *serialized, char *optr, int *retsize) +lwgeom_force3dz_recursive(char *serialized, char *optr, size_t *retsize) { LWGEOM_INSPECTED *inspected; int i,j,k; @@ -1361,7 +1366,7 @@ lwgeom_force3d_recursive(char *serialized, char *optr, int *retsize) #ifdef DEBUG - elog(NOTICE, "lwgeom_force3d_recursive: call"); + elog(NOTICE, "lwgeom_force3dz_recursive: call"); #endif type = lwgeom_getType(serialized[0]); @@ -1369,47 +1374,40 @@ lwgeom_force3d_recursive(char *serialized, char *optr, int *retsize) if ( type == POINTTYPE ) { point = lwpoint_deserialize(serialized); - if ( TYPE_NDIMS(point->type) < 3 ) - { - newpts.ndims = 3; - newpts.npoints = 1; - newpts.serialized_pointlist = lwalloc(sizeof(POINT3D)); - loc = newpts.serialized_pointlist; - getPoint3d_p(point->point, 0, loc); - point->point = &newpts; - } + TYPE_SETZM(newpts.dims, 1, 0); + newpts.npoints = 1; + newpts.serialized_pointlist = lwalloc(sizeof(POINT3DZ)); + loc = newpts.serialized_pointlist; + getPoint3dz_p(point->point, 0, (POINT3DZ *)loc); + point->point = &newpts; TYPE_SETZM(point->type, 1, 0); lwpoint_serialize_buf(point, optr, retsize); #ifdef DEBUG -elog(NOTICE, "lwgeom_force3d_recursive: it's a point, size:%d", *retsize); +elog(NOTICE, "lwgeom_force3dz_recursive: it's a point, size:%d", *retsize); #endif return; } if ( type == LINETYPE ) { + line = lwline_deserialize(serialized); #ifdef DEBUG -elog(NOTICE, "lwgeom_force3d_recursive: it's a line"); +elog(NOTICE, "lwgeom_force3dz_recursive: it's a line"); #endif - line = lwline_deserialize(serialized); - if ( TYPE_NDIMS(line->type) < 3 ) + TYPE_SETZM(newpts.dims, 1, 0); + newpts.npoints = line->points->npoints; + newpts.serialized_pointlist = lwalloc(sizeof(POINT3DZ)*line->points->npoints); + loc = newpts.serialized_pointlist; + for (j=0; jpoints->npoints; j++) { - newpts.ndims = 3; - newpts.npoints = line->points->npoints; - newpts.serialized_pointlist = lwalloc(24*line->points->npoints); - loc = newpts.serialized_pointlist; - for (j=0; jpoints->npoints; j++) - { - getPoint3d_p(line->points, j, loc); - loc+=24; - } - line->points = &newpts; + getPoint3dz_p(line->points, j, (POINT3DZ *)loc); + loc+=sizeof(POINT3DZ); } - + line->points = &newpts; TYPE_SETZM(line->type, 1, 0); lwline_serialize_buf(line, optr, retsize); #ifdef DEBUG -elog(NOTICE, "lwgeom_force3d_recursive: it's a line, size:%d", *retsize); +elog(NOTICE, "lwgeom_force3dz_recursive: it's a line, size:%d", *retsize); #endif return; } @@ -1417,35 +1415,32 @@ elog(NOTICE, "lwgeom_force3d_recursive: it's a line, size:%d", *retsize); if ( type == POLYGONTYPE ) { poly = lwpoly_deserialize(serialized); - if ( TYPE_NDIMS(poly->type) < 3 ) + TYPE_SETZM(newpts.dims, 1, 0); + newpts.npoints = 0; + newpts.serialized_pointlist = lwalloc(1); + nrings = lwalloc(sizeof(POINTARRAY *)*poly->nrings); + loc = newpts.serialized_pointlist; + for (j=0; jnrings; j++) { - newpts.ndims = 3; - newpts.npoints = 0; - newpts.serialized_pointlist = lwalloc(1); - nrings = lwalloc(sizeof(POINTARRAY *)*poly->nrings); - loc = newpts.serialized_pointlist; - for (j=0; jnrings; j++) + POINTARRAY *ring = poly->rings[j]; + POINTARRAY *nring = lwalloc(sizeof(POINTARRAY)); + TYPE_SETZM(nring->dims, 1, 0); + nring->npoints = ring->npoints; + nring->serialized_pointlist = + lwalloc(ring->npoints*sizeof(POINT3DZ)); + loc = nring->serialized_pointlist; + for (k=0; knpoints; k++) { - POINTARRAY *ring = poly->rings[j]; - POINTARRAY *nring = lwalloc(sizeof(POINTARRAY)); - nring->ndims = 3; - nring->npoints = ring->npoints; - nring->serialized_pointlist = - lwalloc(ring->npoints*24); - loc = nring->serialized_pointlist; - for (k=0; knpoints; k++) - { - getPoint3d_p(ring, k, loc); - loc+=24; - } - nrings[j] = nring; + getPoint3dz_p(ring, k, (POINT3DZ *)loc); + loc+=sizeof(POINT3DZ); } - poly->rings = nrings; + nrings[j] = nring; } + poly->rings = nrings; TYPE_SETZM(poly->type, 1, 0); lwpoly_serialize_buf(poly, optr, retsize); #ifdef DEBUG -elog(NOTICE, "lwgeom_force3d_recursive: it's a poly, size:%d", *retsize); +elog(NOTICE, "lwgeom_force3dz_recursive: it's a poly, size:%d", *retsize); #endif return; } @@ -1454,11 +1449,11 @@ elog(NOTICE, "lwgeom_force3d_recursive: it's a poly, size:%d", *retsize); // first and then call us again #ifdef DEBUG -elog(NOTICE, "lwgeom_force3d_recursive: it's a collection (type:%d)", type); +elog(NOTICE, "lwgeom_force3dz_recursive: it's a collection (type:%d)", type); #endif // Add type - *optr = lwgeom_makeType_full(3, lwgeom_hasSRID(serialized[0]), + *optr = lwgeom_makeType_full(1, 0, lwgeom_hasSRID(serialized[0]), type, lwgeom_hasBBOX(serialized[0])); optr++; totsize++; @@ -1496,7 +1491,7 @@ elog(NOTICE, " collection header size:%d", totsize); for (i=0; ingeometries; i++) { char *subgeom = lwgeom_getsubgeometry_inspected(inspected, i); - lwgeom_force3d_recursive(subgeom, optr, &size); + lwgeom_force3dz_recursive(subgeom, optr, &size); totsize += size; optr += size; #ifdef DEBUG @@ -1509,13 +1504,14 @@ elog(NOTICE, " elem %d size: %d (tot: %d)", i, size, totsize); } /* - * Write to already allocated memory 'optr' a 4d version of + * Write to already allocated memory 'optr' a 3dm version of * the given serialized form. - * Pad dimensions are set to 0. + * Higher dimensions in input geometry are discarder. + * If the given version is 2d M is set to 0. * Return number bytes written in given int pointer. */ void -lwgeom_force4d_recursive(char *serialized, char *optr, int *retsize) +lwgeom_force3dm_recursive(char *serialized, char *optr, size_t *retsize) { LWGEOM_INSPECTED *inspected; int i,j,k; @@ -1527,11 +1523,13 @@ lwgeom_force4d_recursive(char *serialized, char *optr, int *retsize) LWPOLY *poly = NULL; POINTARRAY newpts; POINTARRAY **nrings; + POINT3DM *p3dm; char *loc; + char check; #ifdef DEBUG - elog(NOTICE, "lwgeom_force4d_recursive: call"); + elog(NOTICE, "lwgeom_force3dm_recursive: call"); #endif type = lwgeom_getType(serialized[0]); @@ -1539,15 +1537,215 @@ lwgeom_force4d_recursive(char *serialized, char *optr, int *retsize) if ( type == POINTTYPE ) { point = lwpoint_deserialize(serialized); - if ( TYPE_NDIMS(point->type) < 4 ) + TYPE_SETZM(newpts.dims, 0, 1); + newpts.npoints = 1; + newpts.serialized_pointlist = lwalloc(sizeof(POINT3DM)); + loc = newpts.serialized_pointlist; + p3dm = (POINT3DM *)loc; + getPoint3dm_p(point->point, 0, p3dm); + point->point = &newpts; + TYPE_SETZM(point->type, 0, 1); + lwpoint_serialize_buf(point, optr, retsize); + +#ifdef DEBUG +lwnotice("lwgeom_force3dm_recursive returning"); +#endif + return; + } + + if ( type == LINETYPE ) + { + line = lwline_deserialize(serialized); +#ifdef DEBUG +elog(NOTICE, "lwgeom_force3dm_recursive: it's a line with %d points", line->points->npoints); +#endif + TYPE_SETZM(newpts.dims, 0, 1); + newpts.npoints = line->points->npoints; + newpts.serialized_pointlist = lwalloc(sizeof(POINT3DM)*line->points->npoints); +#ifdef DEBUG +elog(NOTICE, "lwgeom_force3dm_recursive: %d bytes pointlist allocated", sizeof(POINT3DM)*line->points->npoints); +#endif + + loc = newpts.serialized_pointlist; + check = TYPE_NDIMS(line->points->dims); + lwnotice("line->points ndims: %d", check); + for (j=0; jpoints->npoints; j++) + { + lwnotice("line->points ndims: %d", check); + getPoint3dm_p(line->points, j, (POINT3DM *)loc); + lwnotice("line->points ndims: %d", check); + if ( check != TYPE_NDIMS(line->points->dims) ) + { + lwerror("getPoint3dm_p messed with input pointarray"); + return; + } + loc+=sizeof(POINT3DM); + } + line->points = &newpts; + TYPE_SETZM(line->type, 0, 1); + lwline_serialize_buf(line, optr, retsize); + +#ifdef DEBUG +lwnotice("lwgeom_force3dm_recursive returning"); +#endif + return; + } + + if ( type == POLYGONTYPE ) + { + poly = lwpoly_deserialize(serialized); + TYPE_SETZM(newpts.dims, 0, 1); + newpts.npoints = 0; + newpts.serialized_pointlist = lwalloc(1); + nrings = lwalloc(sizeof(POINTARRAY *)*poly->nrings); + loc = newpts.serialized_pointlist; + for (j=0; jnrings; j++) { - newpts.ndims = 4; - newpts.npoints = 1; - newpts.serialized_pointlist = lwalloc(sizeof(POINT4D)); - loc = newpts.serialized_pointlist; - getPoint4d_p(point->point, 0, loc); - point->point = &newpts; + POINTARRAY *ring = poly->rings[j]; + POINTARRAY *nring = lwalloc(sizeof(POINTARRAY)); + TYPE_SETZM(nring->dims, 0, 1); + nring->npoints = ring->npoints; + nring->serialized_pointlist = + lwalloc(ring->npoints*sizeof(POINT3DM)); + loc = nring->serialized_pointlist; + for (k=0; knpoints; k++) + { + getPoint3dm_p(ring, k, (POINT3DM *)loc); + loc+=sizeof(POINT3DM); + } + nrings[j] = nring; } + poly->rings = nrings; + TYPE_SETZM(poly->type, 0, 1); + lwpoly_serialize_buf(poly, optr, retsize); + +#ifdef DEBUG +lwnotice("lwgeom_force3dm_recursive returning"); +#endif + return; + } + + if ( type != MULTIPOINTTYPE && type != MULTIPOLYGONTYPE && + type != MULTILINETYPE && type != COLLECTIONTYPE ) + { + lwerror("lwgeom_force3dm_recursive: unknown geometry: %d", + type); + } + + // OK, this is a collection, so we write down its metadata + // first and then call us again + +#ifdef DEBUG +lwnotice("lwgeom_force3dm_recursive: it's a collection (%s)", lwgeom_typename(type)); +#endif + + + // Add type + optr[0] = lwgeom_makeType_full(0, 1, lwgeom_hasSRID(serialized[0]), + type, lwgeom_hasBBOX(serialized[0])); + optr++; + totsize++; + loc=serialized+1; + +#ifdef DEBUG + lwnotice("lwgeom_force3dm_recursive: added collection type (%s) - size:%d", lwgeom_typename(type), totsize); +#endif + + // Add BBOX if any + if (lwgeom_hasBBOX(serialized[0])) + { + memcpy(optr, loc, sizeof(BOX2DFLOAT4)); + optr += sizeof(BOX2DFLOAT4); + totsize += sizeof(BOX2DFLOAT4); + loc += sizeof(BOX2DFLOAT4); +#ifdef DEBUG + lwnotice("lwgeom_force3dm_recursive: added collection bbox - size:%d", totsize); +#endif + } + + // Add SRID if any + if (lwgeom_hasSRID(serialized[0])) + { + memcpy(optr, loc, 4); + optr += 4; + totsize += 4; + loc += 4; +#ifdef DEBUG + lwnotice("lwgeom_force3dm_recursive: added collection SRID - size:%d", totsize); +#endif + } + + // Add numsubobjects + memcpy(optr, loc, sizeof(uint32)); + optr += sizeof(uint32); + totsize += sizeof(uint32); + loc += sizeof(uint32); +#ifdef DEBUG + lwnotice("lwgeom_force3dm_recursive: added collection ngeoms - size:%d", totsize); +#endif + +#ifdef DEBUG + lwnotice("lwgeom_force3dm_recursive: inspecting subgeoms"); +#endif + // Now recurse for each suboject + inspected = lwgeom_inspect(serialized); + for (i=0; ingeometries; i++) + { + char *subgeom = lwgeom_getsubgeometry_inspected(inspected, i); + lwgeom_force3dm_recursive(subgeom, optr, &size); + totsize += size; + optr += size; +#ifdef DEBUG +lwnotice("lwgeom_force3dm_recursive: added elem %d size: %d (tot: %d)", + i, size, totsize); +#endif + } + pfree_inspected(inspected); + +#ifdef DEBUG +lwnotice("lwgeom_force3dm_recursive returning"); +#endif + + if ( retsize ) *retsize = totsize; +} + +/* + * Write to already allocated memory 'optr' a 4d version of + * the given serialized form. + * Pad dimensions are set to 0 (this might be z, m or both). + * Return number bytes written in given int pointer. + */ +void +lwgeom_force4d_recursive(char *serialized, char *optr, size_t *retsize) +{ + LWGEOM_INSPECTED *inspected; + int i,j,k; + int totsize=0; + int size=0; + int type; + LWPOINT *point = NULL; + LWLINE *line = NULL; + LWPOLY *poly = NULL; + POINTARRAY newpts; + POINTARRAY **nrings; + char *loc; + + +#ifdef DEBUG + elog(NOTICE, "lwgeom_force4d_recursive: call"); +#endif + + type = lwgeom_getType(serialized[0]); + + if ( type == POINTTYPE ) + { + point = lwpoint_deserialize(serialized); + TYPE_SETZM(newpts.dims, 1, 1); + newpts.npoints = 1; + newpts.serialized_pointlist = lwalloc(sizeof(POINT4D)); + loc = newpts.serialized_pointlist; + getPoint4d_p(point->point, 0, (POINT4D *)loc); + point->point = &newpts; TYPE_SETZM(point->type, 1, 1); lwpoint_serialize_buf(point, optr, retsize); #ifdef DEBUG @@ -1562,20 +1760,16 @@ elog(NOTICE, "lwgeom_force4d_recursive: it's a point, size:%d", *retsize); elog(NOTICE, "lwgeom_force4d_recursive: it's a line"); #endif line = lwline_deserialize(serialized); - if ( TYPE_NDIMS(line->type) < 4 ) + TYPE_SETZM(newpts.dims, 1, 1); + newpts.npoints = line->points->npoints; + newpts.serialized_pointlist = lwalloc(sizeof(POINT4D)*line->points->npoints); + loc = newpts.serialized_pointlist; + for (j=0; jpoints->npoints; j++) { - newpts.ndims = 4; - newpts.npoints = line->points->npoints; - newpts.serialized_pointlist = lwalloc(sizeof(POINT4D)*line->points->npoints); - loc = newpts.serialized_pointlist; - for (j=0; jpoints->npoints; j++) - { - getPoint4d_p(line->points, j, loc); - loc+=sizeof(POINT4D); - } - line->points = &newpts; + getPoint4d_p(line->points, j, (POINT4D *)loc); + loc+=sizeof(POINT4D); } - + line->points = &newpts; TYPE_SETZM(line->type, 1, 1); lwline_serialize_buf(line, optr, retsize); #ifdef DEBUG @@ -1587,31 +1781,28 @@ elog(NOTICE, "lwgeom_force4d_recursive: it's a line, size:%d", *retsize); if ( type == POLYGONTYPE ) { poly = lwpoly_deserialize(serialized); - if ( TYPE_NDIMS(poly->type) < 4 ) + TYPE_SETZM(newpts.dims, 1, 1); + newpts.npoints = 0; + newpts.serialized_pointlist = lwalloc(1); + nrings = lwalloc(sizeof(POINTARRAY *)*poly->nrings); + loc = newpts.serialized_pointlist; + for (j=0; jnrings; j++) { - newpts.ndims = 4; - newpts.npoints = 0; - newpts.serialized_pointlist = lwalloc(1); - nrings = lwalloc(sizeof(POINTARRAY *)*poly->nrings); - loc = newpts.serialized_pointlist; - for (j=0; jnrings; j++) + POINTARRAY *ring = poly->rings[j]; + POINTARRAY *nring = lwalloc(sizeof(POINTARRAY)); + TYPE_SETZM(nring->dims, 1, 1); + nring->npoints = ring->npoints; + nring->serialized_pointlist = + lwalloc(ring->npoints*sizeof(POINT4D)); + loc = nring->serialized_pointlist; + for (k=0; knpoints; k++) { - POINTARRAY *ring = poly->rings[j]; - POINTARRAY *nring = lwalloc(sizeof(POINTARRAY)); - nring->ndims = 4; - nring->npoints = ring->npoints; - nring->serialized_pointlist = - lwalloc(ring->npoints*sizeof(POINT4D)); - loc = nring->serialized_pointlist; - for (k=0; knpoints; k++) - { - getPoint4d_p(ring, k, loc); - loc+=sizeof(POINT4D); - } - nrings[j] = nring; + getPoint4d_p(ring, k, (POINT4D *)loc); + loc+=sizeof(POINT4D); } - poly->rings = nrings; + nrings[j] = nring; } + poly->rings = nrings; TYPE_SETZM(poly->type, 1, 1); lwpoly_serialize_buf(poly, optr, retsize); #ifdef DEBUG @@ -1628,7 +1819,9 @@ elog(NOTICE, "lwgeom_force4d_recursive: it's a collection (type:%d)", type); #endif // Add type - *optr = lwgeom_makeType_full(4, lwgeom_hasSRID(serialized[0]), + *optr = lwgeom_makeType_full( + 1, 1, + lwgeom_hasSRID(serialized[0]), type, lwgeom_hasBBOX(serialized[0])); optr++; totsize++; @@ -1704,9 +1897,9 @@ Datum LWGEOM_force_2d(PG_FUNCTION_ARGS) PG_RETURN_POINTER(result); } -// transform input geometry to 3d if not 3d already -PG_FUNCTION_INFO_V1(LWGEOM_force_3d); -Datum LWGEOM_force_3d(PG_FUNCTION_ARGS) +// transform input geometry to 3dz if not 3dz already +PG_FUNCTION_INFO_V1(LWGEOM_force_3dz); +Datum LWGEOM_force_3dz(PG_FUNCTION_ARGS) { PG_LWGEOM *geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); PG_LWGEOM *result; @@ -1716,7 +1909,7 @@ Datum LWGEOM_force_3d(PG_FUNCTION_ARGS) olddims = lwgeom_ndims(geom->type); // already 3d - if ( olddims == 3 ) PG_RETURN_POINTER(geom); + if ( olddims == 3 && TYPE_HASZ(geom->type) ) PG_RETURN_POINTER(geom); if ( olddims > 3 ) { result = (PG_LWGEOM *) lwalloc(geom->size); @@ -1725,7 +1918,40 @@ Datum LWGEOM_force_3d(PG_FUNCTION_ARGS) result = (PG_LWGEOM *) lwalloc(geom->size*1.5); } - lwgeom_force3d_recursive(SERIALIZED_FORM(geom), + lwgeom_force3dz_recursive(SERIALIZED_FORM(geom), + SERIALIZED_FORM(result), &size); + + // we can safely avoid this... memory will be freed at + // end of query processing anyway. + //result = lwrealloc(result, size+4); + + result->size = size+4; + + PG_RETURN_POINTER(result); +} + +// transform input geometry to 3dm if not 3dm already +PG_FUNCTION_INFO_V1(LWGEOM_force_3dm); +Datum LWGEOM_force_3dm(PG_FUNCTION_ARGS) +{ + PG_LWGEOM *geom = (PG_LWGEOM *)PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)); + PG_LWGEOM *result; + int olddims; + int32 size = 0; + + olddims = lwgeom_ndims(geom->type); + + // already 3dm + if ( olddims == 3 && TYPE_HASM(geom->type) ) PG_RETURN_POINTER(geom); + + if ( olddims > 3 ) { + result = (PG_LWGEOM *)lwalloc(geom->size); + } else { + // allocate double as memory a larger for safety + result = (PG_LWGEOM *) lwalloc(geom->size*1.5); + } + + lwgeom_force3dm_recursive(SERIALIZED_FORM(geom), SERIALIZED_FORM(result), &size); // we can safely avoid this... memory will be freed at @@ -2018,7 +2244,8 @@ dump_lwexploded(LWGEOM_EXPLODED *exploded) { int i; - elog(NOTICE, "SRID=%d ndims=%d", exploded->SRID, exploded->ndims); + elog(NOTICE, "SRID=%d ndims=%d", exploded->SRID, + TYPE_NDIMS(exploded->dims)); elog(NOTICE, "%d points, %d lines, %d polygons", exploded->npoints, exploded->nlines, exploded->npolys); @@ -2430,11 +2657,11 @@ Datum LWGEOM_expand(PG_FUNCTION_ARGS) // Construct point array pa[0] = lwalloc(sizeof(POINTARRAY)); pa[0]->serialized_pointlist = (char *)pts; - pa[0]->ndims = 2; + TYPE_SETZM(pa[0]->dims, 0, 0); pa[0]->npoints = 5; // Construct polygon - poly = lwpoly_construct(2, SRID, lwgeom_hasBBOX(geom->type), 1, pa); + poly = lwpoly_construct(0, 0, SRID, lwgeom_hasBBOX(geom->type), 1, pa); // Serialize polygon ser = lwpoly_serialize(poly); @@ -2497,11 +2724,13 @@ Datum LWGEOM_envelope(PG_FUNCTION_ARGS) // Construct point array pa[0] = lwalloc(sizeof(POINTARRAY)); pa[0]->serialized_pointlist = (char *)pts; - pa[0]->ndims = 2; + TYPE_SETZM(pa[0]->dims, 0, 0); pa[0]->npoints = 5; - // Construct polygon - poly = lwpoly_construct(2, SRID, lwgeom_hasBBOX(geom->type), 1, pa); + // Construct polygon 2d + poly = lwpoly_construct( + 0, 0, + SRID, lwgeom_hasBBOX(geom->type), 1, pa); // Serialize polygon ser = lwpoly_serialize(poly); @@ -2537,7 +2766,7 @@ Datum centroid(PG_FUNCTION_ARGS) LWPOINT *point; PG_LWGEOM *result; POINTARRAY *ring, *pa; - POINT3D *p, cent; + POINT3DZ *p, cent; int i,j,k; uint32 num_points_tot = 0; char *srl; @@ -2556,10 +2785,10 @@ Datum centroid(PG_FUNCTION_ARGS) ring = poly->rings[j]; for (k=0; knpoints-1; k++) { - p = (POINT3D *)getPoint(ring, k); + p = (POINT3DZ *)getPoint(ring, k); tot_x += p->x; tot_y += p->y; - if ( ring->ndims > 2 ) tot_z += p->z; + if ( TYPE_HASZ(ring->dims) ) tot_z += p->z; } num_points_tot += ring->npoints-1; } @@ -2603,14 +2832,14 @@ segmentize2d_ptarray(POINTARRAY *ipa, double dist) POINT4D pbuf; POINTARRAY *opa; int maxpoints = ipa->npoints; - int ptsize = ipa->ndims * sizeof(double); + int ptsize = pointArray_ptsize(ipa); int ipoff=0; // input point offset pbuf.x = pbuf.y = pbuf.z = pbuf.m = 0; // Initial storage opa = (POINTARRAY *)lwalloc(ptsize * maxpoints); - opa->ndims = ipa->ndims; + opa->dims = ipa->dims; opa->npoints = 0; opa->serialized_pointlist = (char *)lwalloc(maxpoints*ptsize); diff --git a/lwgeom/lwgeom_geos.c b/lwgeom/lwgeom_geos.c index 493ed5aed..b96701475 100644 --- a/lwgeom/lwgeom_geos.c +++ b/lwgeom/lwgeom_geos.c @@ -1882,7 +1882,7 @@ lwpoint_from_geometry(Geometry *g, char want3d) POINTARRAY *pa; LWPOINT *point; POINT3D *pts; - size_t ptsize = want3d ? sizeof(POINT3D) : sizeof(POINT2D); + size_t ptsize = want3d ? sizeof(POINT3DZ) : sizeof(POINT2D); #ifdef DEBUG_GEOS2POSTGIS elog(NOTICE, "lwpoint_from_geometry: point size %d", ptsize); @@ -1890,7 +1890,7 @@ lwpoint_from_geometry(Geometry *g, char want3d) // Construct point array pa = (POINTARRAY *)lwalloc(sizeof(POINTARRAY)); - pa->ndims = want3d ? 3 : 2; + TYPE_SETZM(pa->dims, want3d, 0); pa->npoints = 1; // Fill point array @@ -1900,7 +1900,10 @@ lwpoint_from_geometry(Geometry *g, char want3d) GEOSdeleteChar( (char*) pts); // Construct LWPOINT - point = lwpoint_construct(pa->ndims, -1, 0, pa); + point = lwpoint_construct( + TYPE_HASZ(pa->dims), + TYPE_HASM(pa->dims), + -1, 0, pa); return point; } @@ -1925,7 +1928,7 @@ lwline_from_geometry(Geometry *g, char want3d) // Construct point array pa = (POINTARRAY *)palloc(sizeof(POINTARRAY)); - pa->ndims = want3d ? 3 : 2; + TYPE_SETZM(pa->dims, want3d, 0); pa->npoints = npoints; // Fill point array @@ -1940,7 +1943,10 @@ lwline_from_geometry(Geometry *g, char want3d) GEOSdeleteChar( (char*) pts); // Construct LWPOINT - line = lwline_construct(pa->ndims, -1, 0, pa); + line = lwline_construct( + TYPE_HASZ(pa->dims), + TYPE_HASM(pa->dims), + -1, 0, pa); return line; } @@ -1972,7 +1978,7 @@ lwpoly_from_geometry(Geometry *g, char want3d) npoints = GEOSGetNumCoordinate(GEOSGetExteriorRing(g)); rings[0] = (POINTARRAY *)palloc(sizeof(POINTARRAY)); pa = rings[0]; - pa->ndims = ndims; + TYPE_SETZM(pa->dims, want3d, 0); pa->npoints = npoints; // Fill point array @@ -1991,7 +1997,7 @@ lwpoly_from_geometry(Geometry *g, char want3d) npoints = GEOSGetNumCoordinate(GEOSGetInteriorRingN(g, j)); rings[j+1] = (POINTARRAY *)palloc(sizeof(POINTARRAY)); pa = rings[j+1]; - pa->ndims = ndims; + TYPE_SETZM(pa->dims, want3d, 0); pa->npoints = npoints; // Fill point array @@ -2006,7 +2012,10 @@ lwpoly_from_geometry(Geometry *g, char want3d) } // Construct LWPOLY - poly = lwpoly_construct(pa->ndims, -1, 0, nrings+1, rings); + poly = lwpoly_construct( + TYPE_HASZ(pa->dims), + TYPE_HASM(pa->dims), + -1, 0, nrings+1, rings); return poly; } @@ -2018,7 +2027,6 @@ lwcollection_from_geometry(Geometry *geom, char want3d) uint32 ngeoms; LWGEOM **geoms; LWCOLLECTION *ret; - int ndims = want3d ? 3 : 2; int type = GEOSGeometryTypeId(geom) ; int SRID = GEOSGetSRID(geom); char wantbbox = 0; @@ -2045,7 +2053,9 @@ lwcollection_from_geometry(Geometry *geom, char want3d) #endif } - ret = lwcollection_construct(type, ndims, SRID, + ret = lwcollection_construct(type, + want3d, 0, + SRID, wantbbox, ngeoms, geoms); return ret; } diff --git a/lwgeom/lwgeom_gml.c b/lwgeom/lwgeom_gml.c index 1a34bba75..fe0bce1e0 100644 --- a/lwgeom/lwgeom_gml.c +++ b/lwgeom/lwgeom_gml.c @@ -403,7 +403,7 @@ asgml_inspected(LWGEOM_INSPECTED *insp, char *srs) static size_t pointArray_GMLsize(POINTARRAY *pa) { - return pa->ndims * pa->npoints * (SHOW_DIGS+(pa->ndims-1)); + return TYPE_NDIMS(pa->dims) * pa->npoints * (SHOW_DIGS+(TYPE_NDIMS(pa->dims)-1)); } static size_t @@ -415,7 +415,7 @@ pointArray_toGML(POINTARRAY *pa, char *output) ptr = output; - if ( pa->ndims == 2 ) + if ( ! TYPE_HASZ(pa->dims) ) { for (i=0; inpoints; i++) { @@ -426,7 +426,7 @@ pointArray_toGML(POINTARRAY *pa, char *output) precision, pt->y); } } - else if ( pa->ndims == 3 ) + else { for (i=0; inpoints; i++) { @@ -438,19 +438,6 @@ pointArray_toGML(POINTARRAY *pa, char *output) precision, pt->z); } } - else if ( pa->ndims == 4 ) - { - for (i=0; inpoints; i++) - { - pt = (POINT4D *)getPoint(pa, i); - if ( i ) ptr += sprintf(ptr, " "); - ptr += sprintf(ptr, "%.*g,%.*g,%.*g,%.*g", - precision, pt->x, - precision, pt->y, - precision, pt->z, - precision, pt->m); - } - } return ptr-output; } @@ -515,6 +502,9 @@ getSRSbySRID(int SRID) /********************************************************************** * $Log$ + * Revision 1.5 2004/10/05 16:28:34 strk + * Added ZM dimensions flags knowledge. + * * Revision 1.4 2004/09/29 10:50:30 strk * Big layout change. * lwgeom.h is public API diff --git a/lwgeom/lwgeom_inout.c b/lwgeom/lwgeom_inout.c index bfd95bb2b..4f918a451 100644 --- a/lwgeom/lwgeom_inout.c +++ b/lwgeom/lwgeom_inout.c @@ -511,7 +511,9 @@ Datum LWGEOM_addBBOX(PG_FUNCTION_ARGS) result = palloc(size);// 16 for bbox2d memcpy(result,&size,4); // size - result->type = lwgeom_makeType_full(lwgeom_ndims(old_type), + result->type = lwgeom_makeType_full( + TYPE_HASZ(old_type), + TYPE_HASM(old_type), lwgeom_hasSRID(old_type), lwgeom_getType(old_type), 1); // copy in bbox memcpy(result->data, &box, sizeof(BOX2DFLOAT4)); diff --git a/lwgeom/lwgeom_ogc.c b/lwgeom/lwgeom_ogc.c index 925f05599..cf59b0935 100644 --- a/lwgeom/lwgeom_ogc.c +++ b/lwgeom/lwgeom_ogc.c @@ -333,7 +333,10 @@ Datum LWGEOM_exteriorring_polygon(PG_FUNCTION_ARGS) extring = poly->rings[0]; // This is a LWLINE constructed by exterior ring POINTARRAY - line = lwline_construct(TYPE_NDIMS(poly->type), poly->SRID, + line = lwline_construct( + TYPE_HASZ(poly->type), + TYPE_HASM(poly->type), + poly->SRID, lwgeom_hasBBOX(geom->type), extring); // Now we serialized it (copying data) @@ -417,7 +420,10 @@ Datum LWGEOM_interiorringn_polygon(PG_FUNCTION_ARGS) ring = poly->rings[wanted_index+1]; // This is a LWLINE constructed by exterior ring POINTARRAY - line = lwline_construct(TYPE_NDIMS(poly->type), poly->SRID, + line = lwline_construct( + TYPE_HASZ(poly->type), + TYPE_HASM(poly->type), + poly->SRID, lwgeom_hasBBOX(geom->type), ring); // Now we serialized it (copying data) @@ -474,11 +480,11 @@ Datum LWGEOM_pointn_linestring(PG_FUNCTION_ARGS) // Construct a point array pts = pointArray_construct(getPoint(line->points, wanted_index), - line->points->ndims, 1); + TYPE_HASZ(line->type), TYPE_HASM(line->type), 1); // Construct an LWPOINT - point = lwpoint_construct(line->points->ndims, lwgeom_getSRID(geom), - lwgeom_hasBBOX(geom->type), pts); + point = lwpoint_construct(TYPE_HASZ(line->type), TYPE_HASM(line->type), + lwgeom_getSRID(geom), lwgeom_hasBBOX(geom->type), pts); // Serialized the point serializedpoint = lwpoint_serialize(point); @@ -501,7 +507,7 @@ Datum LWGEOM_x_point(PG_FUNCTION_ARGS) PG_LWGEOM *geom; LWGEOM_INSPECTED *inspected; LWPOINT *point = NULL; - POINT3D *p; + POINT2D *p; int i; geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); @@ -517,7 +523,7 @@ Datum LWGEOM_x_point(PG_FUNCTION_ARGS) if ( point == NULL ) PG_RETURN_NULL(); // Ok, now we have a point, let's get X - p = (POINT3D *)getPoint(point->point, 0); + p = (POINT2D *)getPoint(point->point, 0); PG_RETURN_FLOAT8(p->x); } @@ -530,7 +536,7 @@ Datum LWGEOM_y_point(PG_FUNCTION_ARGS) PG_LWGEOM *geom; LWGEOM_INSPECTED *inspected; LWPOINT *point = NULL; - POINT3D *p; + POINT2D *p; int i; geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); @@ -546,7 +552,7 @@ Datum LWGEOM_y_point(PG_FUNCTION_ARGS) if ( point == NULL ) PG_RETURN_NULL(); // Ok, now we have a point, let's get X - p = (POINT3D *)getPoint(point->point, 0); + p = (POINT2D *)getPoint(point->point, 0); PG_RETURN_FLOAT8(p->y); } @@ -560,13 +566,13 @@ Datum LWGEOM_z_point(PG_FUNCTION_ARGS) PG_LWGEOM *geom; LWGEOM_INSPECTED *inspected; LWPOINT *point = NULL; - POINT3D *p; + POINT3DZ p; int i; geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); // if there's no Z return 0 - if ( lwgeom_ndims(geom->type) < 3 ) PG_RETURN_FLOAT8(0.0); + if ( ! TYPE_HASZ(geom->type) ) PG_RETURN_FLOAT8(0.0); inspected = lwgeom_inspect(SERIALIZED_FORM(geom)); @@ -580,9 +586,9 @@ Datum LWGEOM_z_point(PG_FUNCTION_ARGS) if ( point == NULL ) PG_RETURN_NULL(); // Ok, now we have a point, let's get X - p = (POINT3D *)getPoint(point->point, 0); + lwpoint_getPoint3dz_p(point, &p); - PG_RETURN_FLOAT8(p->z); + PG_RETURN_FLOAT8(p.z); } // StartPoint(GEOMETRY) -- find the first linestring in GEOMETRY, @@ -616,10 +622,14 @@ Datum LWGEOM_startpoint_linestring(PG_FUNCTION_ARGS) // Construct a point array pts = pointArray_construct(getPoint(line->points, 0), - line->points->ndims, 1); + TYPE_HASZ(line->type), + TYPE_HASM(line->type), 1); // Construct an LWPOINT - point = lwpoint_construct(line->points->ndims, lwgeom_getSRID(geom), + point = lwpoint_construct( + TYPE_HASZ(line->type), + TYPE_HASM(line->type), + lwgeom_getSRID(geom), lwgeom_hasBBOX(geom->type), pts); // Serialized the point @@ -667,10 +677,14 @@ Datum LWGEOM_endpoint_linestring(PG_FUNCTION_ARGS) // Construct a point array pts = pointArray_construct( getPoint(line->points, line->points->npoints-1), - line->points->ndims, 1); + TYPE_HASZ(line->type), + TYPE_HASM(line->type), 1); // Construct an LWPOINT - point = lwpoint_construct(line->points->ndims, lwgeom_getSRID(geom), + point = lwpoint_construct( + TYPE_HASZ(line->type), + TYPE_HASM(line->type), + lwgeom_getSRID(geom), lwgeom_hasBBOX(geom->type), pts); // Serialized the point diff --git a/lwgeom/lwgeom_spheroid.c b/lwgeom/lwgeom_spheroid.c index 014b6212d..470518d8d 100644 --- a/lwgeom/lwgeom_spheroid.c +++ b/lwgeom/lwgeom_spheroid.c @@ -284,19 +284,22 @@ double lwgeom_pointarray_length_ellipse(POINTARRAY *pts, SPHEROID *sphere) if ( pts->npoints < 2 ) return 0.0; // compute 2d length if 3d is not available - if ( pts->ndims < 3 ) + if ( TYPE_NDIMS(pts->dims) < 3 ) { return lwgeom_pointarray_length2d_ellipse(pts, sphere); } for (i=0; inpoints-1;i++) { - POINT3D *frm = (POINT3D *)getPoint(pts, i); - POINT3D *to = (POINT3D *)getPoint(pts, i+1); + POINT3DZ frm; + POINT3DZ to; + getPoint3dz_p(pts, i, &frm); + getPoint3dz_p(pts, i+1, &to); + double distellips = distance_ellipse( - frm->y*M_PI/180.0, frm->x*M_PI/180.0, - to->y*M_PI/180.0, to->x*M_PI/180.0, sphere); - dist += sqrt(distellips*distellips + (frm->z*frm->z)); + frm.y*M_PI/180.0, frm.x*M_PI/180.0, + to.y*M_PI/180.0, to.x*M_PI/180.0, sphere); + dist += sqrt(distellips*distellips + (frm.z*frm.z)); } return dist; } diff --git a/lwgeom/lwgparse.c b/lwgeom/lwgparse.c index b63cfb397..33444a3a4 100644 --- a/lwgeom/lwgparse.c +++ b/lwgeom/lwgparse.c @@ -18,6 +18,8 @@ #include */ +void set_zm(char z, char m); +void close_parser(void); static int endian_check_int = 1; // dont modify this!!! diff --git a/lwgeom/lwline.c b/lwgeom/lwline.c index f5b156046..87a6a6a5e 100644 --- a/lwgeom/lwline.c +++ b/lwgeom/lwline.c @@ -11,12 +11,12 @@ // construct a new LWLINE. points will *NOT* be copied // use SRID=-1 for unknown SRID (will have 8bit type's S = 0) LWLINE * -lwline_construct(int ndims, int SRID, char wantbbox, POINTARRAY *points) +lwline_construct(char hasz, char hasm, int SRID, char wantbbox, POINTARRAY *points) { LWLINE *result; result = (LWLINE*) lwalloc( sizeof(LWLINE)); - result->type = lwgeom_makeType_full(ndims, (SRID!=-1), LINETYPE, + result->type = lwgeom_makeType_full(hasz, hasm, (SRID!=-1), LINETYPE, wantbbox); result->SRID = SRID; result->points = points; @@ -28,7 +28,8 @@ lwline_construct(int ndims, int SRID, char wantbbox, POINTARRAY *points) // construct a proper LWLINE. // serialized_form should point to the 8bit type format (with type = 2) // See serialized form doc -LWLINE *lwline_deserialize(char *serialized_form) +LWLINE * +lwline_deserialize(char *serialized_form) { unsigned char type; LWLINE *result; @@ -76,8 +77,7 @@ LWLINE *lwline_deserialize(char *serialized_form) npoints = get_uint32(loc); //lwnotice("line npoints = %d", npoints); loc +=4; - pa = pointArray_construct( loc, lwgeom_ndims(type), npoints); - + pa = pointArray_construct(loc, TYPE_HASZ(type), TYPE_HASM(type), npoints); result->points = pa; return result; @@ -85,7 +85,8 @@ LWLINE *lwline_deserialize(char *serialized_form) // convert this line into its serialize form // result's first char will be the 8bit type. See serialized form doc -char *lwline_serialize(LWLINE *line) +char * +lwline_serialize(LWLINE *line) { size_t size, retsize; char * result; @@ -108,74 +109,81 @@ char *lwline_serialize(LWLINE *line) // the given buffer, and returning number of bytes written into // the given int pointer. // result's first char will be the 8bit type. See serialized form doc -void lwline_serialize_buf(LWLINE *line, char *buf, size_t *retsize) +void +lwline_serialize_buf(LWLINE *line, char *buf, size_t *retsize) { - int size=1; // type byte + size_t size=1; // type byte char hasSRID; - int t; char *loc; - int ptsize = sizeof(double)*TYPE_NDIMS(line->type); + int ptsize = pointArray_ptsize(line->points); + + if ( ptsize != sizeof(double)*TYPE_NDIMS(line->type) ) + { + lwerror("lwline_serialize_buf: line has %d dims, its pointarray has %d dims"); + } + +#ifdef DEBUG_CALLS + lwnotice("lwline_serialize_buf(%p, %p, %p) called", + line, buf, retsize); +#endif if (line == NULL) lwerror("lwline_serialize:: given null line"); hasSRID = (line->SRID != -1); - buf[0] = (unsigned char) lwgeom_makeType_full(TYPE_NDIMS(line->type), - hasSRID, LINETYPE, TYPE_HASBBOX(line->type)); + buf[0] = line->type; loc = buf+1; +#ifdef DEBUG + lwnotice("lwline_serialize_buf added type (%d)", line->type); +#endif + if (TYPE_HASBBOX(line->type)) { lwgeom_compute_bbox_p((LWGEOM *)line, (BOX2DFLOAT4 *)loc); loc += sizeof(BOX2DFLOAT4); - size += sizeof(BOX2DFLOAT4); // bvol +#ifdef DEBUG + lwnotice("lwline_serialize_buf added BBOX"); +#endif } if (hasSRID) { memcpy(loc, &line->SRID, sizeof(int32)); - size +=4; //4 byte SRID - loc += 4; + loc += sizeof(int32); +#ifdef DEBUG + lwnotice("lwline_serialize_buf added SRID"); +#endif } memcpy(loc, &line->points->npoints, sizeof(int32)); loc +=4; - size+=4; // npoints + +#ifdef DEBUG + lwnotice("lwline_serialize_buf added npoints (%d)", + line->points->npoints); +#endif //copy in points + memcpy(loc, line->points->serialized_pointlist, + ptsize*line->points->npoints); + loc += ptsize * line->points->npoints; -//lwnotice(" line serialize - size = %i", size); +#ifdef DEBUG + lwnotice("lwline_serialize_buf copied serialized_pointlist (%d bytes)", + ptsize * line->points->npoints); +#endif - if (TYPE_NDIMS(line->type) == 3) - { - for (t=0; t< line->points->npoints;t++) - { - getPoint3d_p(line->points, t, loc); - loc += 24; // size of a 3d point - } - } - else if (TYPE_NDIMS(line->type) == 2) - { - for (t=0; t< line->points->npoints;t++) - { - getPoint2d_p(line->points, t, loc); - loc += 16; // size of a 2d point - } - } - else if (TYPE_NDIMS(line->type) == 4) - { - for (t=0; t< line->points->npoints;t++) - { - getPoint4d_p(line->points, t, loc); - loc += 32; // size of a 2d point - } - } - size += ptsize * line->points->npoints; + if (retsize) *retsize = loc-buf; - //printBYTES((unsigned char *)result, size); + //printBYTES((unsigned char *)result, loc-buf); + +#ifdef DEBUG_CALLS + lwnotice("lwline_serialize_buf returning (loc: %p, size: %d)", + loc, loc-buf); +#endif - if (retsize) *retsize = size; } // find bounding box (standard one) zmin=zmax=0 if 2d (might change to NaN) @@ -203,7 +211,7 @@ lwline_serialize_size(LWLINE *line) if ( line->SRID != -1 ) size += 4; // SRID if ( TYPE_HASBBOX(line->type) ) size += sizeof(BOX2DFLOAT4); - size += sizeof(double)*TYPE_NDIMS(line->type)*line->points->npoints; // points + size += pointArray_ptsize(line->points)*line->points->npoints;; size += 4; // npoints #ifdef DEBUG_CALLS @@ -224,10 +232,14 @@ uint32 lwgeom_size_line(const char *serialized_line) { int type = (unsigned char) serialized_line[0]; - uint32 result =1; //type + uint32 result = 1; //type const char *loc; uint32 npoints; +#ifdef DEBUG_CALLS + lwnotice("lwgeom_size_line called"); +#endif + if ( lwgeom_getType(type) != LINETYPE) lwerror("lwgeom_size_line::attempt to find the length of a non-line"); @@ -240,31 +252,23 @@ lwgeom_size_line(const char *serialized_line) result +=sizeof(BOX2DFLOAT4); } - if ( lwgeom_hasSRID(type)) - { - loc += 4; // type + SRID - result +=4; - } - - // we've read the type (1 byte) and SRID (4 bytes, if present) - - npoints = get_uint32(loc); - result += 4; //npoints - - if (lwgeom_ndims(type) ==3) - { - return result + npoints * 24; - } - else if (lwgeom_ndims(type) ==2) - { - return result+ npoints * 16; - } - else if (lwgeom_ndims(type) ==4) - { - return result+ npoints * 32; - } - lwerror("lwgeom_size_line :: invalid ndims"); - return 0; //never get here + if ( lwgeom_hasSRID(type)) + { + loc += 4; // type + SRID + result +=4; + } + + // we've read the type (1 byte) and SRID (4 bytes, if present) + npoints = get_uint32(loc); + result += sizeof(uint32); //npoints + + result += TYPE_NDIMS(type) * sizeof(double); + +#ifdef DEBUG_CALLS + lwnotice("lwgeom_size_line returning %d", result); +#endif + + return result; } void printLWLINE(LWLINE *line) @@ -333,7 +337,10 @@ lwline_add(const LWLINE *to, uint32 where, const LWGEOM *what) if ( TYPE_GETTYPE(what->type) == LINETYPE ) newtype = MULTILINETYPE; else newtype = COLLECTIONTYPE; - col = lwcollection_construct(newtype, TYPE_NDIMS(to->type), to->SRID, + col = lwcollection_construct(newtype, + TYPE_HASZ(to->type), + TYPE_HASM(to->type), + to->SRID, ( TYPE_HASBBOX(what->type) || TYPE_HASBBOX(to->type) ), 2, geoms); diff --git a/lwgeom/lwmline.c b/lwgeom/lwmline.c index f724d988f..c995949e8 100644 --- a/lwgeom/lwmline.c +++ b/lwgeom/lwmline.c @@ -79,7 +79,10 @@ lwmline_add(const LWMLINE *to, uint32 where, const LWGEOM *what) if ( TYPE_GETTYPE(what->type) == LINETYPE ) newtype = MULTILINETYPE; else newtype = COLLECTIONTYPE; - col = lwcollection_construct(newtype, TYPE_NDIMS(to->type), to->SRID, + col = lwcollection_construct(newtype, + TYPE_HASZ(to->type), + TYPE_HASM(to->type), + to->SRID, ( TYPE_HASBBOX(what->type) || TYPE_HASBBOX(to->type) ), to->ngeoms+1, geoms); diff --git a/lwgeom/lwmpoint.c b/lwgeom/lwmpoint.c index 0ccfa3147..cc19d443b 100644 --- a/lwgeom/lwmpoint.c +++ b/lwgeom/lwmpoint.c @@ -79,7 +79,8 @@ lwmpoint_add(const LWMPOINT *to, uint32 where, const LWGEOM *what) if ( TYPE_GETTYPE(what->type) == POINTTYPE ) newtype = MULTIPOINTTYPE; else newtype = COLLECTIONTYPE; - col = lwcollection_construct(newtype, TYPE_NDIMS(to->type), + col = lwcollection_construct(newtype, + TYPE_HASZ(to->type), TYPE_HASM(to->type), to->SRID, ( TYPE_HASBBOX(what->type) || TYPE_HASBBOX(to->type) ), to->ngeoms+1, geoms); diff --git a/lwgeom/lwmpoly.c b/lwgeom/lwmpoly.c index 0f9c1b8ba..0b6e8a84c 100644 --- a/lwgeom/lwmpoly.c +++ b/lwgeom/lwmpoly.c @@ -85,7 +85,10 @@ lwmpoly_add(const LWMPOLY *to, uint32 where, const LWGEOM *what) if ( TYPE_GETTYPE(what->type) == POLYGONTYPE ) newtype = MULTIPOLYGONTYPE; else newtype = COLLECTIONTYPE; - col = lwcollection_construct(newtype, TYPE_NDIMS(to->type), to->SRID, + col = lwcollection_construct(newtype, + TYPE_HASZ(to->type), + TYPE_HASM(to->type), + to->SRID, ( TYPE_HASBBOX(what->type) || TYPE_HASBBOX(to->type) ), to->ngeoms+1, geoms); diff --git a/lwgeom/lwpoint.c b/lwgeom/lwpoint.c index a1b69946a..6f701caa9 100644 --- a/lwgeom/lwpoint.c +++ b/lwgeom/lwpoint.c @@ -36,6 +36,7 @@ lwpoint_serialize_buf(LWPOINT *point, char *buf, size_t *retsize) char hasSRID; char *loc; + //printLWPOINT(point); #ifdef DEBUG_CALLS lwnotice("lwpoint_serialize_buf(%p, %p) called", point, buf); #endif @@ -47,7 +48,8 @@ lwpoint_serialize_buf(LWPOINT *point, char *buf, size_t *retsize) size += sizeof(double)*TYPE_NDIMS(point->type); - buf[0] = (unsigned char) lwgeom_makeType_full(TYPE_NDIMS(point->type), + buf[0] = (unsigned char) lwgeom_makeType_full( + TYPE_HASZ(point->type), TYPE_HASM(point->type), hasSRID, POINTTYPE, TYPE_HASBBOX(point->type)); loc = buf+1; @@ -65,9 +67,17 @@ lwpoint_serialize_buf(LWPOINT *point, char *buf, size_t *retsize) //copy in points - if (TYPE_NDIMS(point->type) == 3) getPoint3d_p(point->point, 0, loc); - else if (TYPE_NDIMS(point->type) == 2) getPoint2d_p(point->point, 0, loc); - else if (TYPE_NDIMS(point->type) == 4) getPoint4d_p(point->point, 0, loc); + if (TYPE_NDIMS(point->type) == 3) + { + if (TYPE_HASZ(point->type)) + getPoint3dz_p(point->point, 0, (POINT3DZ *)loc); + else + getPoint3dm_p(point->point, 0, (POINT3DM *)loc); + } + else if (TYPE_NDIMS(point->type) == 2) + getPoint2d_p(point->point, 0, (POINT2D *)loc); + else if (TYPE_NDIMS(point->type) == 4) + getPoint4d_p(point->point, 0, (POINT4D *)loc); if (retsize) *retsize = size; } @@ -96,27 +106,27 @@ lwpoint_findbbox(LWPOINT *point) // convenience functions to hide the POINTARRAY // TODO: obsolete this -POINT2D -lwpoint_getPoint2d(const LWPOINT *point) +int +lwpoint_getPoint2d_p(const LWPOINT *point, POINT2D *out) { - POINT2D result; - - if (point == NULL) - return result; - - return getPoint2d(point->point,0); + return getPoint2d_p(point->point, 0, out); } // convenience functions to hide the POINTARRAY -POINT3D -lwpoint_getPoint3d(const LWPOINT *point) +int +lwpoint_getPoint3dz_p(const LWPOINT *point, POINT3DZ *out) { - POINT3D result; - - if (point == NULL) - return result; - - return getPoint3d(point->point,0); + return getPoint3dz_p(point->point,0,out); +} +int +lwpoint_getPoint3dm_p(const LWPOINT *point, POINT3DM *out) +{ + return getPoint3dm_p(point->point,0,out); +} +int +lwpoint_getPoint4d_p(const LWPOINT *point, POINT4D *out) +{ + return getPoint4d_p(point->point,0,out); } // find length of this deserialized point @@ -144,7 +154,7 @@ lwpoint_serialize_size(LWPOINT *point) // construct a new point. point will not be copied // use SRID=-1 for unknown SRID (will have 8bit type's S = 0) LWPOINT * -lwpoint_construct(int ndims, int SRID, char wantbbox, POINTARRAY *point) +lwpoint_construct(char hasZ, char hasM, int SRID, char wantbbox, POINTARRAY *point) { LWPOINT *result ; @@ -152,8 +162,8 @@ lwpoint_construct(int ndims, int SRID, char wantbbox, POINTARRAY *point) return NULL; // error result = lwalloc(sizeof(LWPOINT)); - result->type = lwgeom_makeType_full(ndims, (SRID!=-1), POINTTYPE, - wantbbox); + result->type = lwgeom_makeType_full(hasZ, hasM, (SRID!=-1), + POINTTYPE, wantbbox); result->SRID = SRID; result->point = point; @@ -208,7 +218,7 @@ lwpoint_deserialize(char *serialized_form) // we've read the type (1 byte) and SRID (4 bytes, if present) - pa = pointArray_construct(loc, lwgeom_ndims(type), 1); + pa = pointArray_construct(loc, TYPE_HASZ(type), TYPE_HASM(type), 1); result->point = pa; @@ -292,7 +302,10 @@ lwpoint_add(const LWPOINT *to, uint32 where, const LWGEOM *what) if ( TYPE_GETTYPE(what->type) == POINTTYPE ) newtype = MULTIPOINTTYPE; else newtype = COLLECTIONTYPE; - col = lwcollection_construct(newtype, TYPE_NDIMS(to->type), to->SRID, + col = lwcollection_construct(newtype, + TYPE_HASZ(to->type), + TYPE_HASM(to->type), + to->SRID, ( TYPE_HASBBOX(what->type) || TYPE_HASBBOX(to->type) ), 2, geoms); diff --git a/lwgeom/lwpoly.c b/lwgeom/lwpoly.c index 21d734852..6630ac5c8 100644 --- a/lwgeom/lwpoly.c +++ b/lwgeom/lwpoly.c @@ -10,12 +10,12 @@ // construct a new LWPOLY. arrays (points/points per ring) will NOT be copied // use SRID=-1 for unknown SRID (will have 8bit type's S = 0) LWPOLY * -lwpoly_construct(int ndims, int SRID, char wantbbox, int nrings, POINTARRAY **points) +lwpoly_construct(char hasz, char hasm, int SRID, char wantbbox, int nrings, POINTARRAY **points) { LWPOLY *result; result = (LWPOLY*) lwalloc(sizeof(LWPOLY)); - result->type = lwgeom_makeType_full(ndims, (SRID!=-1), POLYGONTYPE, + result->type = lwgeom_makeType_full(hasz, hasm, (SRID!=-1), POLYGONTYPE, wantbbox); result->SRID = SRID; result->nrings = nrings; @@ -35,7 +35,7 @@ lwpoly_deserialize(char *serialized_form) LWPOLY *result; uint32 nrings; - int ndims; + int ndims, hasz, hasm; uint32 npoints; unsigned char type; char *loc; @@ -52,10 +52,12 @@ lwpoly_deserialize(char *serialized_form) type = (unsigned char) serialized_form[0]; result->type = type; - ndims = lwgeom_ndims(type); + ndims = TYPE_NDIMS(type); + hasz = TYPE_HASZ(type); + hasm = TYPE_HASM(type); loc = serialized_form; - if ( lwgeom_getType(type) != POLYGONTYPE) + if ( TYPE_GETTYPE(type) != POLYGONTYPE) { lwerror("lwpoly_deserialize called with arg of type %d", lwgeom_getType(type)); @@ -91,13 +93,8 @@ lwpoly_deserialize(char *serialized_form) npoints = get_uint32(loc); loc +=4; - result->rings[t] = pointArray_construct(loc, ndims, npoints); - if (ndims == 3) - loc += 24*npoints; - else if (ndims == 2) - loc += 16*npoints; - else if (ndims == 4) - loc += 32*npoints; + result->rings[t] = pointArray_construct(loc, hasz, hasm, npoints); + loc += sizeof(double)*ndims*npoints; } return result; @@ -153,7 +150,8 @@ lwpoly_serialize_buf(LWPOLY *poly, char *buf, size_t *retsize) } size += sizeof(double)*TYPE_NDIMS(poly->type)*total_points; - buf[0] = (unsigned char) lwgeom_makeType_full(TYPE_NDIMS(poly->type), + buf[0] = (unsigned char) lwgeom_makeType_full( + TYPE_HASZ(poly->type), TYPE_HASM(poly->type), hasSRID, POLYGONTYPE, TYPE_HASBBOX(poly->type)); loc = buf+1; @@ -182,17 +180,28 @@ lwpoly_serialize_buf(LWPOLY *poly, char *buf, size_t *retsize) loc+=4; if (TYPE_NDIMS(poly->type) == 3) { - for (u=0;utype) ) + { + for (u=0;utype) == 2) { for (u=0;utype) == POLYGONTYPE ) newtype = MULTIPOLYGONTYPE; else newtype = COLLECTIONTYPE; - col = lwcollection_construct(newtype, TYPE_NDIMS(to->type), to->SRID, + col = lwcollection_construct(newtype, + TYPE_HASZ(to->type), + TYPE_HASM(to->type), + to->SRID, ( TYPE_HASBBOX(what->type) || TYPE_HASBBOX(to->type) ), 2, geoms); diff --git a/lwgeom/lwpostgis.sql.in b/lwgeom/lwpostgis.sql.in index e4aeba9d1..9fc57c89b 100644 --- a/lwgeom/lwpostgis.sql.in +++ b/lwgeom/lwpostgis.sql.in @@ -1539,9 +1539,20 @@ CREATEFUNCTION force_2d(geometry) AS '@MODULE_FILENAME@', 'LWGEOM_force_2d' LANGUAGE 'C' WITH (isstrict); +CREATEFUNCTION force_3dz(geometry) + RETURNS geometry + AS '@MODULE_FILENAME@', 'LWGEOM_force_3dz' + LANGUAGE 'C' WITH (isstrict); + +-- an alias for force_3dz CREATEFUNCTION force_3d(geometry) RETURNS geometry - AS '@MODULE_FILENAME@', 'LWGEOM_force_3d' + AS '@MODULE_FILENAME@', 'LWGEOM_force_3dz' + LANGUAGE 'C' WITH (isstrict); + +CREATEFUNCTION force_3dm(geometry) + RETURNS geometry + AS '@MODULE_FILENAME@', 'LWGEOM_force_3dm' LANGUAGE 'C' WITH (isstrict); CREATEFUNCTION force_4d(geometry) diff --git a/lwgeom/wktparse.lex b/lwgeom/wktparse.lex index e5ee602d6..fd0f8d2a4 100644 --- a/lwgeom/wktparse.lex +++ b/lwgeom/wktparse.lex @@ -13,6 +13,7 @@ void init_parser(const char *src); void close_parser(void); int lwg_parse_yywrap(void); +int lwg_parse_yylex(void); static YY_BUFFER_STATE buf_state; void init_parser(const char *src) { BEGIN(0);buf_state = lwg_parse_yy_scan_string(src); } diff --git a/lwgeom/wktparse.y b/lwgeom/wktparse.y index 6cc24ccd6..71d6eedd8 100644 --- a/lwgeom/wktparse.y +++ b/lwgeom/wktparse.y @@ -9,6 +9,7 @@ %{ #include "wktparse.h" +void set_zm(char z, char m); %} %start geometry -- 2.50.1