]> granicus.if.org Git - postgis/commitdiff
Added ZM dimensions flags knowledge.
authorSandro Santilli <strk@keybit.net>
Tue, 5 Oct 2004 16:28:34 +0000 (16:28 +0000)
committerSandro Santilli <strk@keybit.net>
Tue, 5 Oct 2004 16:28:34 +0000 (16:28 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@929 b70326c6-7e19-0410-871a-916f4a2858ee

23 files changed:
lwgeom/liblwgeom.h
lwgeom/lwcollection.c
lwgeom/lwgeom_api.c
lwgeom/lwgeom_box2dfloat4.c
lwgeom/lwgeom_box3d.c
lwgeom/lwgeom_chip.c
lwgeom/lwgeom_functions_analytic.c
lwgeom/lwgeom_functions_basic.c
lwgeom/lwgeom_geos.c
lwgeom/lwgeom_gml.c
lwgeom/lwgeom_inout.c
lwgeom/lwgeom_ogc.c
lwgeom/lwgeom_spheroid.c
lwgeom/lwgparse.c
lwgeom/lwline.c
lwgeom/lwmline.c
lwgeom/lwmpoint.c
lwgeom/lwmpoly.c
lwgeom/lwpoint.c
lwgeom/lwpoly.c
lwgeom/lwpostgis.sql.in
lwgeom/wktparse.lex
lwgeom/wktparse.y

index a689e6a444725d68ce94d3c451c621e48a9ed39c..58dd4af4e7419ed26166a300ad1c7291d0a016fb 100644 (file)
@@ -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);
index 43a06922e4006eb040ec96932fbd2a13a1b35df0..cab581ea9bab4ba7fec3213c3663a5add1b5e576 100644 (file)
@@ -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);
index 700e343759dd48e1af57300d24abf9c72e706e50..483f094afcaade363aa5509341c2d1b82dfaab03 100644 (file)
@@ -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;
+       POINT3Dpt;
        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;t<pa->npoints;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; t<pa->npoints;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; i<inspected->ngeometries; 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;
 
index a395e8b58666d67424fdf2bdae7fb3111476395c..347cb2e921581c7c93698c02d421d105aba5d98e 100644 (file)
@@ -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);
index 496bf7bc7c88d928da69dd4f169f9e56b877edc9..1f735c60032d23bb2c3bd93fb701d387ec8234b9 100644 (file)
@@ -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);
index 2af28c79707ec2b5bd79d895382e7b9862a7ecd9..82c1475553d67c6dae022f698b2481be3f95d212 100644 (file)
@@ -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);
index 36fd5d75747e8e0673016429a28ad2c4da60810e..af7ceb052daec7d5c693894219a9041d115073d1 100644 (file)
@@ -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));
index a0a80799be5e0ee0e31d7de516954229e3e90127..a8514fd340bff36d53ee7e98248a00d05fa40477 100644 (file)
@@ -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; i<pts->npoints-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; i<pa->npoints; 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; i<pa->npoints; 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; j<line->points->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; j<line->points->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; j<poly->nrings; 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; j<poly->nrings; 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; k<ring->npoints; 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; k<ring->npoints; 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; i<inspected->ngeometries; 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; j<line->points->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; j<poly->nrings; 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; k<ring->npoints; 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; i<inspected->ngeometries; 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; j<line->points->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; j<line->points->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; j<poly->nrings; 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; j<poly->nrings; 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; k<ring->npoints; 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; k<ring->npoints; 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; k<ring->npoints-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);
 
index 493ed5aed141e181e54bf8a4914a9870965ffedb..b96701475971d9c48f971a31315d9d52090456ac 100644 (file)
@@ -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;
 }
index 1a34bba754956ab97c7bf67b320aeaed51f55ac9..fe0bce1e047f8bbd2be8c8b58c08a9af39b8cc0e 100644 (file)
@@ -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; i<pa->npoints; i++)
                {
@@ -426,7 +426,7 @@ pointArray_toGML(POINTARRAY *pa, char *output)
                                precision, pt->y);
                }
        }
-       else if ( pa->ndims == 3 )
+       else 
        {
                for (i=0; i<pa->npoints; i++)
                {
@@ -438,19 +438,6 @@ pointArray_toGML(POINTARRAY *pa, char *output)
                                precision, pt->z);
                }
        }
-       else if ( pa->ndims == 4 )
-       {
-               for (i=0; i<pa->npoints; 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
index bfd95bb2b6aec2bc03175047fd8671dca37c33b8..4f918a451d8c6a8e7c585736f0a7337f530e4c29 100644 (file)
@@ -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));
index 925f05599d0c6d3d860bedada84679fd1367eb3d..cf59b09354672915039b2882f297a190ee55d70a 100644 (file)
@@ -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;
+       POINT3Dp;
        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
index 014b6212df9d116aa755bd7001c3f08c9ab035b6..470518d8d203557d91b219689f0d7ada2f4744aa 100644 (file)
@@ -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; i<pts->npoints-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;
 }
index b63cfb397200ca364a8fae32109a9f352a8adc5c..33444a3a43125510d43c4c6090b327e64224de8b 100644 (file)
@@ -18,6 +18,8 @@
 #include <netinet/ip.h>
 */
 
+void set_zm(char z, char m);
+void close_parser(void);
 
 static int endian_check_int = 1; // dont modify this!!!
 
index f5b15604619a410bd50c5c0614f8fea4ddcf9d08..87a6a6a5ebde3bac259e46be0d7366bab575c9d9 100644 (file)
 // 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);
        
index f724d988ffdc4468916917bf64ee824018629be1..c995949e84ed57c8503a959e7aa4760a8ec27a7f 100644 (file)
@@ -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);
        
index 0ccfa31474aa3409e3b1bb7431cd39f0daaea7da..cc19d443ba0f567e6bb37d3f6f7f6498fbf7fed3 100644 (file)
@@ -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);
index 0f9c1b8ba8e8227c7872d6e9d0dc762853013dab..0b6e8a84c9ad882d6cf6a09bf3b20d02fa31e006 100644 (file)
@@ -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);
        
index a1b69946a49efa223d21789b1f0009b518aa0b7e..6f701caa9dfbfe8d3ed8e2b9df054a5c4391b8e1 100644 (file)
@@ -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);
        
index 21d7348524cb64816d7f587e825ee03968978d6e..6630ac5c8d9b2ff53cac37f5bfebdfa4caacaeff 100644 (file)
 // 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;u<npoints;u++)
+                       if ( TYPE_HASZ(poly->type) )
+                       {
+                               for (u=0;u<npoints;u++)
+                               {
+                                       getPoint3dz_p(pa, u, (POINT3DZ *)loc);
+                                       loc+= 24;
+                               }
+                       }
+                       else
                        {
-                               getPoint3d_p(pa, u, loc);
-                               loc+= 24;
+                               for (u=0;u<npoints;u++)
+                               {
+                                       getPoint3dm_p(pa, u, (POINT3DM *)loc);
+                                       loc+= 24;
+                               }
                        }
                }
                else if (TYPE_NDIMS(poly->type) == 2)
                {
                        for (u=0;u<npoints;u++)
                        {
-                               getPoint2d_p(pa, u, loc);
+                               getPoint2d_p(pa, u, (POINT2D *)loc);
                                loc+= 16;
                        }
                }
@@ -200,7 +209,7 @@ lwpoly_serialize_buf(LWPOLY *poly, char *buf, size_t *retsize)
                {
                        for (u=0;u<npoints;u++)
                        {
-                               getPoint4d_p(pa, u, loc);
+                               getPoint4d_p(pa, u, (POINT4D *)loc);
                                loc+= 32;
                        }
                }
@@ -439,7 +448,10 @@ lwpoly_add(const LWPOLY *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) ),
                2, geoms);
        
index e4aeba9d147992ec19405e563fda7d9e76611778..9fc57c89b53f5fc7727f7cff38e03a2f1d8a9d40 100644 (file)
@@ -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) 
index e5ee602d657e9c94b427ad122a10691819342e95..fd0f8d2a449d9a0e29f108b39ce6e8d99920e22d 100644 (file)
@@ -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); }
index 6cc24ccd634928a0b186fde65e5f1e3519784154..71d6eedd86f92aa1bd8990961a3e988e235c98ea 100644 (file)
@@ -9,6 +9,7 @@
 %{
 #include "wktparse.h"
 
+void set_zm(char z, char m);
 %}
 
 %start geometry