//liblwgeom.h
+#define DEBUG 1
+#define DEBUG_CALLS 1
+
typedef void* (*lwallocator)(size_t size);
typedef void* (*lwreallocator)(void *mem, size_t size);
} 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
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;
// 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
// 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.
// 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
#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
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
// 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.
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.
// 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.
typedef struct
{
int SRID;
- int ndims;
+ unsigned char dims;
uint32 npoints;
char **points;
uint32 nlines;
// 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
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);
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);
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;
}
if (retsize) *retsize = size;
+
+#ifdef DEBUG_CALLS
+ lwnotice("lwcollection_serialize_buf returning");
+#endif
}
int
}
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;
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);
// 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
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);
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;
}
// 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
// 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;
// calculate the bounding box of a set of points
// returns a lwalloced BOX3D, or NULL on empty array.
// zmin/zmax values are set to NO_Z_VALUE if not available.
-BOX3D *pointArray_bbox(const POINTARRAY *pa)
+BOX3D *
+pointArray_bbox(const POINTARRAY *pa)
{
int t;
BOX3D *result;
- POINT3D *pt;
+ POINT3DZ pt;
int npoints = pa->npoints;
#ifdef DEBUG
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;
#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;
}
}
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);
}
int
lwgeom_ndims(unsigned char type)
{
- return TYPE_NDIMS(type);
+ return TYPE_NDIMS(type);
}
// has M ?
//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);
}
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]) )
// 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);
// 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;
char *loc;
if (nsubgeometries == 0)
- return lwgeom_constructempty(SRID,ndims);
+ return lwgeom_constructempty(SRID, hasz, hasm);
lengths = lwalloc(sizeof(int32) * nsubgeometries);
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);
// 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;
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);
// 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);
}
- ngeoms = get_uint32(loc);
+ ngeoms = get_uint32(loc);
loc +=4;
result += 4; // numgeoms
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);
}
}
// 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)
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;
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 )
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++)
{
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));
}
}
- expcoll->ndims = exp1->ndims;
+ expcoll->dims = exp1->dims;
expcoll->SRID = exp1->SRID;
return expcoll;
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;
}
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;
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;
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;
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;
// 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);
// 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);
// 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);
* --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
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;
// 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);
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;
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);
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);
/* 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));
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);
}
//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;
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) ) );
{
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;
* 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;
#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++;
}
/*
- * 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;
#ifdef DEBUG
- elog(NOTICE, "lwgeom_force3d_recursive: call");
+ elog(NOTICE, "lwgeom_force3dz_recursive: call");
#endif
type = lwgeom_getType(serialized[0]);
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;
}
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;
}
// 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++;
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
}
/*
- * 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;
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]);
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
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
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
#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++;
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;
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);
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
{
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);
// 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);
// 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);
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;
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;
}
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);
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);
// 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
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;
}
// 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
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;
}
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
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
}
// 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;
}
uint32 ngeoms;
LWGEOM **geoms;
LWCOLLECTION *ret;
- int ndims = want3d ? 3 : 2;
int type = GEOSGeometryTypeId(geom) ;
int SRID = GEOSGetSRID(geom);
char wantbbox = 0;
#endif
}
- ret = lwcollection_construct(type, ndims, SRID,
+ ret = lwcollection_construct(type,
+ want3d, 0,
+ SRID,
wantbbox, ngeoms, geoms);
return ret;
}
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
ptr = output;
- if ( pa->ndims == 2 )
+ if ( ! TYPE_HASZ(pa->dims) )
{
for (i=0; i<pa->npoints; i++)
{
precision, pt->y);
}
}
- else if ( pa->ndims == 3 )
+ else
{
for (i=0; i<pa->npoints; i++)
{
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;
}
/**********************************************************************
* $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
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));
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)
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)
// 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);
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));
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);
}
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));
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);
}
PG_LWGEOM *geom;
LWGEOM_INSPECTED *inspected;
LWPOINT *point = NULL;
- POINT3D *p;
+ POINT3DZ p;
int i;
geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
// if there's no Z return 0
- if ( lwgeom_ndims(geom->type) < 3 ) PG_RETURN_FLOAT8(0.0);
+ if ( ! TYPE_HASZ(geom->type) ) PG_RETURN_FLOAT8(0.0);
inspected = lwgeom_inspect(SERIALIZED_FORM(geom));
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,
// 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
// 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
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;
}
#include <netinet/ip.h>
*/
+void set_zm(char z, char m);
+void close_parser(void);
static int endian_check_int = 1; // dont modify this!!!
// 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;
// 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;
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;
// 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;
// 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)
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
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");
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)
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);
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);
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);
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);
char hasSRID;
char *loc;
+ //printLWPOINT(point);
#ifdef DEBUG_CALLS
lwnotice("lwpoint_serialize_buf(%p, %p) called", point, buf);
#endif
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;
//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;
}
// 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
// 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 ;
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;
// 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;
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);
// 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;
LWPOLY *result;
uint32 nrings;
- int ndims;
+ int ndims, hasz, hasm;
uint32 npoints;
unsigned char type;
char *loc;
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));
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;
}
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;
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;
}
}
{
for (u=0;u<npoints;u++)
{
- getPoint4d_p(pa, u, loc);
+ getPoint4d_p(pa, u, (POINT4D *)loc);
loc+= 32;
}
}
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);
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)
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); }
%{
#include "wktparse.h"
+void set_zm(char z, char m);
%}
%start geometry