From 7e26ef63c5d76f66d4f73fe9b87eccae838d8880 Mon Sep 17 00:00:00 2001 From: Sandro Santilli Date: Fri, 20 Aug 2004 14:08:41 +0000 Subject: [PATCH] Added Geom{etry,}FromWkb(,[]) funx. Added LWGEOM typedef and SERIALIZED_FORM(LWGEOM) macro. Made lwgeom_setSRID an API function. Added LWGEOM_setAllocator(). git-svn-id: http://svn.osgeo.org/postgis/trunk@710 b70326c6-7e19-0410-871a-916f4a2858ee --- lwgeom/MISSING_OBJECTS | 4 - lwgeom/lwgeom.h | 62 ++++----- lwgeom/lwgeom_api.c | 125 ++++++++++++----- lwgeom/lwgeom_btree.c | 76 ++++++----- lwgeom/lwgeom_functions_basic.c | 73 +++------- lwgeom/lwgeom_inout.c | 233 ++++++++++++++++---------------- lwgeom/lwpostgis.sql.in | 33 +++++ 7 files changed, 327 insertions(+), 279 deletions(-) diff --git a/lwgeom/MISSING_OBJECTS b/lwgeom/MISSING_OBJECTS index 600070978..4efcc46a4 100644 --- a/lwgeom/MISSING_OBJECTS +++ b/lwgeom/MISSING_OBJECTS @@ -74,10 +74,6 @@ FUNC: KEEPING FUNCTION: [max_distance(geometry, geometry)] FUNC: KEEPING FUNCTION: [optimistic_overlap(geometry, geometry, double precision)] FUNC: KEEPING FUNCTION: [segmentize(geometry, double precision)] FUNC: KEEPING FUNCTION: [distance(geometry, geometry)] -FUNC: KEEPING FUNCTION: [geometryfromtext(geometry, integer)] -FUNC: KEEPING FUNCTION: [geometryfromtext(geometry)] -FUNC: KEEPING FUNCTION: [geomfromtext(geometry, integer)] -FUNC: KEEPING FUNCTION: [geomfromtext(geometry)] FUNC: KEEPING FUNCTION: [polyfromtext(geometry, integer)] FUNC: KEEPING FUNCTION: [polygonfromtext(geometry, integer)] FUNC: KEEPING FUNCTION: [polygonfromtext(geometry)] diff --git a/lwgeom/lwgeom.h b/lwgeom/lwgeom.h index cec39ab5b..8676506e3 100644 --- a/lwgeom/lwgeom.h +++ b/lwgeom/lwgeom.h @@ -7,16 +7,10 @@ #include "utils/geo_decls.h" -/* +// This will be used to +typedef void* (*LWGEOM_allocator)(size_t size); -typedef struct -{ - float xmin; - float ymin; - float xmax; - float ymax; - -} BOX2DFLOAT4; +LWGEOM_allocator LWGEOM_setAllocator(LWGEOM_allocator); typedef struct { @@ -24,29 +18,7 @@ typedef struct float ymin; float xmax; float ymax; - char junk[16]; } BOX2DFLOAT4; -typedef struct -{ - double xmin; - double ymin; - double xmax; - double ymax; -} BOX2DFLOAT4; - -*/ - -typedef struct -{ - float xmin; - float ymin; - float xmax; - float ymax; - -} BOX2DFLOAT4; - - - typedef struct { @@ -63,8 +35,7 @@ typedef struct // 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; } POINT3D; // type for 2d points. When you convert this to 3d, the @@ -75,7 +46,6 @@ typedef struct double y; } POINT2D; - typedef struct { double x; @@ -84,8 +54,6 @@ typedef struct double m; } POINT4D; - - // Point array abstracts a lot of the complexity of points and point lists. // It handles miss-alignment in the serialized form, 2d/3d translation // (2d points converted to 3d will have z=0 or NaN) @@ -175,7 +143,6 @@ WHERE */ - // already defined in postgis.h #define POINTTYPE 1 @@ -186,7 +153,23 @@ WHERE #define MULTIPOLYGONTYPE 6 #define COLLECTIONTYPE 7 +/* + * This is the binary representation of lwgeom compatible + * with postgresql varlena struct + */ +typedef struct { + int32 size; + unsigned char type; // encodes ndims, type, bbox presence, + // srid presence + char data[1]; +} LWGEOM; +/* + * Use this macro to extract the char * required + * by most functions from an LWGEOM struct. + * (which is an LWGEOM w/out int32 size casted to char *) + */ +#define SERIALIZED_FORM(x) ((char *)&((x)->type)) extern bool lwgeom_hasSRID(unsigned char type); // true iff S bit is set @@ -415,9 +398,10 @@ extern int lwgeom_seralizedformlength_simple(char *serialized_form); extern int lwgeom_seralizedformlength(char *serialized_form, int geom_number); extern int lwgeom_seralizedformlength_inspected(LWGEOM_INSPECTED *inspected, int geom_number); -//get the SRID from the LWGEOM +// get the SRID from the LWGEOM // none present => -1 -extern int lwgeom_getSRID(char *serialized_form); +extern int lwgeom_getSRID(LWGEOM *lwgeom); +extern LWGEOM *lwgeom_setSRID(LWGEOM *lwgeom, int32 newSRID); //get bounding box of LWGEOM (automatically calls the sub-geometries bbox generators) extern BOX3D *lw_geom_getBB(char *serialized_form); diff --git a/lwgeom/lwgeom_api.c b/lwgeom/lwgeom_api.c index f465371c1..2d1731254 100644 --- a/lwgeom/lwgeom_api.c +++ b/lwgeom/lwgeom_api.c @@ -19,6 +19,8 @@ // This is an implementation of the functions defined in lwgeom.h +static LWGEOM_allocator internal_allocator = malloc; + //forward decs @@ -349,31 +351,32 @@ BOX2DFLOAT4 getbox2d(char *serialized_form) // same as getbox2d, but modifies box instead of returning result on the stack -void getbox2d_p(char *serialized_form, BOX2DFLOAT4 *box) +void +getbox2d_p(char *serialized_form, BOX2DFLOAT4 *box) { - int type = (unsigned char) serialized_form[0]; - char *loc; - BOX3D *box3d; - BOX2DFLOAT4 *box2; + unsigned char type = (unsigned char) serialized_form[0]; + char *loc; + BOX3D *box3d; + BOX2DFLOAT4 *box2; - loc = serialized_form+1; + loc = serialized_form+1; - if (lwgeom_hasBBOX(type)) - { - //woot - this is easy - //elog(NOTICE,"getbox2d has box"); - memcpy(box,loc, sizeof(BOX2DFLOAT4)); - return ; - } + if (lwgeom_hasBBOX(type)) + { + //woot - this is easy +//elog(NOTICE,"getbox2d has box"); + memcpy(box,loc, sizeof(BOX2DFLOAT4)); + return ; + } - //we have to actually compute it! + //we have to actually compute it! //elog(NOTICE,"getbox2d_p:: computing box"); - box3d = lw_geom_getBB_simple(serialized_form); - box2 = box3d_to_box2df(box3d); + box3d = lw_geom_getBB_simple(serialized_form); + box2 = box3d_to_box2df(box3d); - memcpy(box,box2, sizeof(BOX2DFLOAT4)); - pfree(box3d); - pfree(box2); + memcpy(box,box2, sizeof(BOX2DFLOAT4)); + pfree(box3d); + pfree(box2); } //************************************************************************ @@ -706,8 +709,6 @@ int32 get_int32(char *loc) return result; } - - //****************************************************************************** // basic LWLINE functions @@ -2216,27 +2217,87 @@ void printType(unsigned char type) elog(NOTICE,"type 0x%x ==> hasBBOX=%i, hasSRID=%i, ndims=%i, type=%i",(unsigned int) type, lwgeom_hasBBOX(type), lwgeom_hasSRID(type),lwgeom_ndims(type), lwgeom_getType(type)); } +// get the SRID from the LWGEOM +// none present => -1 +int lwgeom_getSRID(LWGEOM *lwgeom) +{ + unsigned char type = lwgeom->type; + char *loc = lwgeom->data; + + if ( ! lwgeom_hasSRID(type)) return -1; + if (lwgeom_hasBBOX(type)) + { + loc += sizeof(BOX2DFLOAT4); + } + return get_int32(lwgeom->data); +} -//get the SRID from the LWGEOM -// none present => -1 -int lwgeom_getSRID(char *serialized_form) +// Set the SRID of a LWGEOM +// Returns a newly allocated LWGEOM object. +// Allocation will be done using the internal_allocator. +LWGEOM *lwgeom_setSRID(LWGEOM *lwgeom, int32 newSRID) { - unsigned char type = (unsigned char) serialized_form[0]; - char *loc; + unsigned char type = lwgeom->type; + int bbox_offset=0; //0=no bbox, otherwise sizeof(BOX2DFLOAT4) + int len,len_new,len_left; + LWGEOM *result; + char *loc_new, *loc_old; + if (lwgeom_hasBBOX(type)) + bbox_offset = sizeof(BOX2DFLOAT4); - loc = serialized_form+1; + len = lwgeom->size; - if (lwgeom_hasBBOX((unsigned char) serialized_form[0])) + if (lwgeom_hasSRID(type)) { - loc += sizeof(BOX2DFLOAT4); + //we create a new one and copy the SRID in + result = internal_allocator(len); + memcpy(result, lwgeom, len); + memcpy(result->data+bbox_offset, &newSRID,4); } + else // need to add one + { + len_new = len + 4;//+4 for SRID + result = internal_allocator(len_new); + memcpy(result, &len_new, 4); // size copy in + result->type = lwgeom_makeType_full(lwgeom_ndims(type), true, lwgeom_getType(type),lwgeom_hasBBOX(type)); - if ( lwgeom_hasSRID(type)) + loc_new = result->data; + loc_old = lwgeom->data; + + len_left = len -4-1;// old length - size - type + + // handle bbox (if there) + + if (lwgeom_hasBBOX(type)) { - return get_int32(loc); + memcpy(loc_new, loc_old, sizeof(BOX2DFLOAT4)) ;//copy in bbox + loc_new += sizeof(BOX2DFLOAT4); + loc_old += sizeof(BOX2DFLOAT4); + len_left -= sizeof(BOX2DFLOAT4); } - return -1; + + //put in SRID + + memcpy(loc_new, &newSRID,4); + loc_new +=4; + memcpy(loc_new, loc_old, len_left); + + // TODO: add SRID presence flag in type. + } + return result; +} + +/* + * Set an allocator function. + * Return current allocator function. + */ +LWGEOM_allocator +LWGEOM_setAllocator(LWGEOM_allocator newallocator) +{ + LWGEOM_allocator oldalloc = internal_allocator; + internal_allocator = newallocator; + return oldalloc; } diff --git a/lwgeom/lwgeom_btree.c b/lwgeom/lwgeom_btree.c index 0a03840a3..4c99dd7e6 100644 --- a/lwgeom/lwgeom_btree.c +++ b/lwgeom/lwgeom_btree.c @@ -25,13 +25,13 @@ Datum lwgeom_ge(PG_FUNCTION_ARGS); Datum lwgeom_gt(PG_FUNCTION_ARGS); Datum lwgeom_cmp(PG_FUNCTION_ARGS); -// #define DEBUG +//#define DEBUG PG_FUNCTION_INFO_V1(lwgeom_lt); Datum lwgeom_lt(PG_FUNCTION_ARGS) { - char *geom1 = (char *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - char *geom2 = (char *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); + LWGEOM *geom1 = (LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + LWGEOM *geom2 = (LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); BOX2DFLOAT4 box1; BOX2DFLOAT4 box2; @@ -39,7 +39,7 @@ Datum lwgeom_lt(PG_FUNCTION_ARGS) elog(NOTICE, "lwgeom_lt called"); #endif - if (lwgeom_getSRID(geom1+4) != lwgeom_getSRID(geom2+4)) + if (lwgeom_getSRID(geom1) != lwgeom_getSRID(geom2)) { elog(ERROR, "Operation on two GEOMETRIES with different SRIDs\n"); @@ -50,10 +50,16 @@ Datum lwgeom_lt(PG_FUNCTION_ARGS) PG_RETURN_NULL(); } - //elog(NOTICE, "SRID check passed"); +#ifdef DEBUG + elog(NOTICE, "lwgeom_lt passed getSRID test"); +#endif + + getbox2d_p(SERIALIZED_FORM(geom1), &box1); + getbox2d_p(SERIALIZED_FORM(geom2), &box2); - getbox2d_p(geom1+4, &box1); - getbox2d_p(geom2+4, &box2); +#ifdef DEBUG + elog(NOTICE, "lwgeom_lt getbox2d_p passed"); +#endif if ( ! FPeq(box1.xmin , box2.xmin) ) { if (box1.xmin < box2.xmin) @@ -81,8 +87,8 @@ Datum lwgeom_lt(PG_FUNCTION_ARGS) PG_FUNCTION_INFO_V1(lwgeom_le); Datum lwgeom_le(PG_FUNCTION_ARGS) { - char *geom1 = (char *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - char *geom2 = (char *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); + LWGEOM *geom1 = (LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + LWGEOM *geom2 = (LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); BOX2DFLOAT4 box1; BOX2DFLOAT4 box2; @@ -90,7 +96,7 @@ Datum lwgeom_le(PG_FUNCTION_ARGS) elog(NOTICE, "lwgeom_le called"); #endif - if (lwgeom_getSRID(geom1+4) != lwgeom_getSRID(geom2+4)) + if (lwgeom_getSRID(geom1) != lwgeom_getSRID(geom2)) { elog(ERROR, "Operation on two GEOMETRIES with different SRIDs\n"); @@ -101,8 +107,8 @@ Datum lwgeom_le(PG_FUNCTION_ARGS) PG_RETURN_NULL(); } - getbox2d_p(geom1+4, &box1); - getbox2d_p(geom2+4, &box2); + getbox2d_p(SERIALIZED_FORM(geom1), &box1); + getbox2d_p(SERIALIZED_FORM(geom2), &box2); if ( ! FPeq(box1.xmin , box2.xmin) ) { if (box1.xmin < box2.xmin) @@ -161,8 +167,8 @@ Datum lwgeom_le(PG_FUNCTION_ARGS) PG_FUNCTION_INFO_V1(lwgeom_eq); Datum lwgeom_eq(PG_FUNCTION_ARGS) { - char *geom1 = (char *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - char *geom2 = (char *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); + LWGEOM *geom1 = (LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + LWGEOM *geom2 = (LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); BOX2DFLOAT4 box1; BOX2DFLOAT4 box2; @@ -170,7 +176,7 @@ Datum lwgeom_eq(PG_FUNCTION_ARGS) elog(NOTICE, "lwgeom_eq called"); #endif - if (lwgeom_getSRID(geom1+4) != lwgeom_getSRID(geom2+4)) + if (lwgeom_getSRID(geom1) != lwgeom_getSRID(geom2)) { elog(ERROR, "Operation on two GEOMETRIES with different SRIDs\n"); @@ -181,8 +187,8 @@ Datum lwgeom_eq(PG_FUNCTION_ARGS) PG_RETURN_NULL(); } - getbox2d_p(geom1+4, &box1); - getbox2d_p(geom2+4, &box2); + getbox2d_p(SERIALIZED_FORM(geom1), &box1); + getbox2d_p(SERIALIZED_FORM(geom2), &box2); if ( ! FPeq(box1.xmin , box2.xmin) ) { @@ -221,8 +227,8 @@ Datum lwgeom_eq(PG_FUNCTION_ARGS) PG_FUNCTION_INFO_V1(lwgeom_ge); Datum lwgeom_ge(PG_FUNCTION_ARGS) { - char *geom1 = (char *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - char *geom2 = (char *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); + LWGEOM *geom1 = (LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + LWGEOM *geom2 = (LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); BOX2DFLOAT4 box1; BOX2DFLOAT4 box2; @@ -230,7 +236,7 @@ Datum lwgeom_ge(PG_FUNCTION_ARGS) elog(NOTICE, "lwgeom_ge called"); #endif - if (lwgeom_getSRID(geom1+4) != lwgeom_getSRID(geom2+4)) + if (lwgeom_getSRID(geom1) != lwgeom_getSRID(geom2)) { elog(ERROR, "Operation on two GEOMETRIES with different SRIDs\n"); @@ -241,8 +247,8 @@ Datum lwgeom_ge(PG_FUNCTION_ARGS) PG_RETURN_NULL(); } - getbox2d_p(geom1+4, &box1); - getbox2d_p(geom2+4, &box2); + getbox2d_p(SERIALIZED_FORM(geom1), &box1); + getbox2d_p(SERIALIZED_FORM(geom2), &box2); if ( ! FPeq(box1.xmin , box2.xmin) ) { if (box1.xmin > box2.xmin) @@ -293,8 +299,8 @@ Datum lwgeom_ge(PG_FUNCTION_ARGS) PG_FUNCTION_INFO_V1(lwgeom_gt); Datum lwgeom_gt(PG_FUNCTION_ARGS) { - char *geom1 = (char *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - char *geom2 = (char *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); + LWGEOM *geom1 = (LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + LWGEOM *geom2 = (LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); BOX2DFLOAT4 box1; BOX2DFLOAT4 box2; @@ -302,7 +308,7 @@ Datum lwgeom_gt(PG_FUNCTION_ARGS) elog(NOTICE, "lwgeom_gt called"); #endif - if (lwgeom_getSRID(geom1+4) != lwgeom_getSRID(geom2+4)) + if (lwgeom_getSRID(geom1) != lwgeom_getSRID(geom2)) { elog(ERROR, "Operation on two GEOMETRIES with different SRIDs\n"); @@ -313,8 +319,8 @@ Datum lwgeom_gt(PG_FUNCTION_ARGS) PG_RETURN_NULL(); } - getbox2d_p(geom1+4, &box1); - getbox2d_p(geom2+4, &box2); + getbox2d_p(SERIALIZED_FORM(geom1), &box1); + getbox2d_p(SERIALIZED_FORM(geom2), &box2); if ( ! FPeq(box1.xmin , box2.xmin) ) { if (box1.xmin > box2.xmin) @@ -361,8 +367,8 @@ Datum lwgeom_gt(PG_FUNCTION_ARGS) PG_FUNCTION_INFO_V1(lwgeom_cmp); Datum lwgeom_cmp(PG_FUNCTION_ARGS) { - char *geom1 = (char *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - char *geom2 = (char *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); + LWGEOM *geom1 = (LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + LWGEOM *geom2 = (LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); BOX2DFLOAT4 box1; BOX2DFLOAT4 box2; @@ -370,7 +376,7 @@ Datum lwgeom_cmp(PG_FUNCTION_ARGS) elog(NOTICE, "lwgeom_cmp called"); #endif - if (lwgeom_getSRID(geom1+4) != lwgeom_getSRID(geom2+4)) + if (lwgeom_getSRID(geom1) != lwgeom_getSRID(geom2)) { elog(ERROR, "Operation on two GEOMETRIES with different SRIDs\n"); @@ -381,8 +387,8 @@ Datum lwgeom_cmp(PG_FUNCTION_ARGS) PG_RETURN_NULL(); } - getbox2d_p(geom1+4, &box1); - getbox2d_p(geom2+4, &box2); + getbox2d_p(SERIALIZED_FORM(geom1), &box1); + getbox2d_p(SERIALIZED_FORM(geom2), &box2); if ( ! FPeq(box1.xmin , box2.xmin) ) { if (box1.xmin < box2.xmin) @@ -441,6 +447,12 @@ Datum lwgeom_cmp(PG_FUNCTION_ARGS) /*********************************************************** * * $Log$ + * Revision 1.3 2004/08/20 14:08:41 strk + * Added Geom{etry,}FromWkb(,[]) funx. + * Added LWGEOM typedef and SERIALIZED_FORM(LWGEOM) macro. + * Made lwgeom_setSRID an API function. + * Added LWGEOM_setAllocator(). + * * Revision 1.2 2004/08/19 13:10:13 strk * fixed typos * diff --git a/lwgeom/lwgeom_functions_basic.c b/lwgeom/lwgeom_functions_basic.c index 43bfa0ad6..e2dab7d0c 100644 --- a/lwgeom/lwgeom_functions_basic.c +++ b/lwgeom/lwgeom_functions_basic.c @@ -28,16 +28,20 @@ Datum LWGEOM_getSRID(PG_FUNCTION_ARGS); Datum LWGEOM_getTYPE(PG_FUNCTION_ARGS); Datum LWGEOM_setSRID(PG_FUNCTION_ARGS); Datum combine_box2d(PG_FUNCTION_ARGS); +Datum lwgeom_mem_size(PG_FUNCTION_ARGS); +static void * +palloc_fn(size_t size) +{ + return palloc(size); +} // getSRID(lwgeom) :: int4 PG_FUNCTION_INFO_V1(LWGEOM_getSRID); Datum LWGEOM_getSRID(PG_FUNCTION_ARGS) { - char *lwgeom = (char *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - int srid = lwgeom_getSRID (lwgeom+4); - - //printBYTES(lwgeom, *((int*)lwgeom) ); + LWGEOM *lwgeom = (LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + int srid = lwgeom_getSRID (lwgeom); PG_RETURN_INT32(srid); } @@ -46,61 +50,16 @@ Datum LWGEOM_getSRID(PG_FUNCTION_ARGS) PG_FUNCTION_INFO_V1(LWGEOM_setSRID); Datum LWGEOM_setSRID(PG_FUNCTION_ARGS) { - char *lwgeom = (char *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - int newSRID = PG_GETARG_INT32(1); - char type = lwgeom[4]; - int bbox_offset =0; //0=no bbox, otherwise sizeof(BOX2DFLOAT4) - int len,len_new,len_left; - char *result; - char *loc_new, *loc_old; - - // I'm totally cheating here - // If it already has an SRID, just overwrite it. - // If it doesnt have an SRID, we'll create it - - if (lwgeom_hasBBOX(type)) - bbox_offset = sizeof(BOX2DFLOAT4); - - len = *((int *)lwgeom); - - if (lwgeom_hasSRID(type)) - { - //we create a new one and copy the SRID in - result = palloc(len); - memcpy(result, lwgeom, len); - memcpy(result+5+bbox_offset, &newSRID,4); - PG_RETURN_POINTER(result); - } - else // need to add one - { - len_new = len + 4;//+4 for SRID - result = palloc(len_new); - memcpy(result, &len_new, 4); // size copy in - result[4] = lwgeom_makeType_full(lwgeom_ndims(type), true, lwgeom_getType(type),lwgeom_hasBBOX(type)); - - - loc_new = result+5; - loc_old = lwgeom+5; - - len_left = len -4-1;// old length - size - type + LWGEOM *lwgeom = (LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + int newSRID = PG_GETARG_INT32(1); + LWGEOM *result; + LWGEOM_allocator oldalloc; - // handle bbox (if there) + oldalloc = LWGEOM_setAllocator(palloc_fn); + result = lwgeom_setSRID(lwgeom, newSRID); + LWGEOM_setAllocator(oldalloc); - if (lwgeom_hasBBOX(type)) - { - memcpy(loc_new, loc_old, sizeof(BOX2DFLOAT4)) ;//copy in bbox - loc_new+= sizeof(BOX2DFLOAT4); - loc_old+= sizeof(BOX2DFLOAT4); - len_left -= sizeof(BOX2DFLOAT4); - } - - //put in SRID - - memcpy(loc_new, &newSRID,4); - loc_new +=4; - memcpy(loc_new, loc_old, len_left); - PG_RETURN_POINTER(result); - } + PG_RETURN_POINTER(result); } //returns a string representation of this geometry's type diff --git a/lwgeom/lwgeom_inout.c b/lwgeom/lwgeom_inout.c index 2d246a85a..4a8a501c4 100644 --- a/lwgeom/lwgeom_inout.c +++ b/lwgeom/lwgeom_inout.c @@ -23,7 +23,6 @@ #include "wktparse.h" void elog_ERROR(const char* string); -void *palloc_fn(size_t size); extern unsigned char parse_hex(char *str); @@ -32,8 +31,8 @@ extern void deparse_hex(unsigned char str, unsigned char *result); extern char *parse_lwgeom_wkt(char *wkt_input); -void *palloc_fn2(size_t size); -void free_fn(void *ptr); +static void *palloc_fn(size_t size); +static void free_fn(void *ptr); @@ -44,10 +43,12 @@ void free_fn(void *ptr); Datum LWGEOMFromWKB(PG_FUNCTION_ARGS); Datum WKBFromLWGEOM(PG_FUNCTION_ARGS); - Datum LWGEOM_in(PG_FUNCTION_ARGS); Datum LWGEOM_out(PG_FUNCTION_ARGS); +// needed for OGC conformance +Datum LWGEOM_from_text(PG_FUNCTION_ARGS); + Datum LWGEOM_asText(PG_FUNCTION_ARGS); Datum LWGEOM_addBBOX(PG_FUNCTION_ARGS); @@ -77,45 +78,43 @@ typedef struct Well_known_bin { PG_FUNCTION_INFO_V1(LWGEOM_in); Datum LWGEOM_in(PG_FUNCTION_ARGS) { - char *str = PG_GETARG_CSTRING(0); - - char *semicolonLoc,start; - + char *str = PG_GETARG_CSTRING(0); + char *semicolonLoc,start; - //determine if its WKB or WKT - - semicolonLoc = strchr(str,';'); - if (semicolonLoc == NULL) - { - start = str[0]; - } - else - { - start =semicolonLoc[1]; // one in - } + //determine if its WKB or WKT - // this is included just for redundancy (new parser can handle wkt and wkb) + semicolonLoc = strchr(str,';'); + if (semicolonLoc == NULL) + { + start=str[0]; + } + else + { + start=semicolonLoc[1]; // one in + } - if ( - ( (start >= '0') && (start <= '9') ) || - ( (start >= 'A') && (start <= 'F') ) - ) - { - //its WKB - //PG_RETURN_POINTER(parse_lwgeom_serialized_form(str)); - PG_RETURN_POINTER( parse_lwgeom_wkt(str) ); // this function handles wkt and wkb (in hex-form) - } - else if ( (start == 'P') || (start == 'L') || (start == 'M') || (start == 'G') || (start == 'p') || (start == 'l') || (start == 'm') || (start == 'g')) - { - // its WKT - PG_RETURN_POINTER( parse_lwgeom_wkt(str) ); // this function handles wkt and wkb (in hex-form) + // this is included just for redundancy (new parser can handle wkt and wkb) - } - else - { - elog(ERROR,"couldnt determine if input lwgeom is WKB or WKT"); - PG_RETURN_NULL(); - } + if ( ( (start >= '0') && (start <= '9') ) || + ( (start >= 'A') && (start <= 'F') )) + { + //its WKB + //PG_RETURN_POINTER(parse_lwgeom_serialized_form(str)); + PG_RETURN_POINTER( parse_lwgeom_wkt(str) ); // this function handles wkt and wkb (in hex-form) + } + else if ( (start == 'P') || (start == 'L') || (start == 'M') || + (start == 'G') || (start == 'p') || (start == 'l') || + (start == 'm') || (start == 'g')) + { + // its WKT + // this function handles wkt and wkb (in hex-form) + PG_RETURN_POINTER( parse_lwgeom_wkt(str) ); + } + else + { + elog(ERROR,"couldnt determine if input lwgeom is WKB or WKT"); + PG_RETURN_NULL(); + } } @@ -128,7 +127,7 @@ PG_FUNCTION_INFO_V1(LWGEOM_out); Datum LWGEOM_out(PG_FUNCTION_ARGS) { char *lwgeom = (char *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - char *result = unparse_WKB(lwgeom,palloc_fn2,free_fn); + char *result = unparse_WKB(lwgeom,palloc_fn,free_fn); PG_RETURN_CSTRING(result); } @@ -198,7 +197,7 @@ Datum WKBFromLWGEOM(PG_FUNCTION_ARGS) char *lwgeom_input = (char *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); // SRID=#; - char *hexized_wkb_srid =unparse_WKB(lwgeom_input,palloc_fn2,free_fn); + char *hexized_wkb_srid =unparse_WKB(lwgeom_input,palloc_fn,free_fn); char *hexized_wkb; // hexized_wkb_srid w/o srid char *result; //wkb @@ -243,6 +242,30 @@ Datum WKBFromLWGEOM(PG_FUNCTION_ARGS) PG_RETURN_POINTER(result); } +//given wkt and SRID, return a geometry +//actually we cheat, postgres will convert the string to a geometry for us... +PG_FUNCTION_INFO_V1(LWGEOM_from_text); +Datum LWGEOM_from_text(PG_FUNCTION_ARGS) +{ + LWGEOM *geom = (LWGEOM *)PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)); + int32 SRID; + LWGEOM *result = NULL; + + // read user-requested SRID if any + if ( PG_NARGS() > 1 ) + { + SRID = PG_GETARG_INT32(1); + if ( SRID != lwgeom_getSRID(geom) ) + { + result = lwgeom_setSRID(geom, SRID); + pfree(geom); + } + } + if ( ! result ) result = geom; + + PG_RETURN_POINTER(result); +} + @@ -480,56 +503,31 @@ unsigned char parse_hex(char *str) return (unsigned char) ((result_high<<4) + result_low); } - -// for the parser/unparser -- it needs memory management functions -void *palloc_fn2(size_t size) -{ - void * result; - - result = palloc(size); -// elog(NOTICE," palloc(%i) at %p",size,result); - return result; -} - -void free_fn(void *ptr) -{ - -// elog(NOTICE," pfree(%p)", ptr); - pfree(ptr); -} - - - - //convert LWGEOM to wkt (in TEXT format) PG_FUNCTION_INFO_V1(LWGEOM_asText); Datum LWGEOM_asText(PG_FUNCTION_ARGS) { - char *lwgeom = (char *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - char *result_cstring = unparse_WKT(lwgeom,palloc_fn2,free_fn); - int len; - - - char *result,*loc_wkt; - char *semicolonLoc; + char *lwgeom = (char *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + char *result_cstring = unparse_WKT(lwgeom,palloc_fn,free_fn); + int len; - semicolonLoc = strchr(result_cstring,';'); + char *result,*loc_wkt; + char *semicolonLoc; - //loc points to start of wkt - if (semicolonLoc == NULL) - loc_wkt = result_cstring; - else - loc_wkt = semicolonLoc +1; + semicolonLoc = strchr(result_cstring,';'); + //loc points to start of wkt + if (semicolonLoc == NULL) loc_wkt = result_cstring; + else loc_wkt = semicolonLoc +1; - len = strlen(loc_wkt)+4; - result = palloc(len); - memcpy(result, &len, 4); + len = strlen(loc_wkt)+4; + result = palloc(len); + memcpy(result, &len, 4); - memcpy(result+4,loc_wkt, len-4); + memcpy(result+4,loc_wkt, len-4); - pfree(result_cstring); - PG_RETURN_POINTER(result); + pfree(result_cstring); + PG_RETURN_POINTER(result); } @@ -537,40 +535,40 @@ Datum LWGEOM_asText(PG_FUNCTION_ARGS) PG_FUNCTION_INFO_V1(LWGEOM_addBBOX); Datum LWGEOM_addBBOX(PG_FUNCTION_ARGS) { - char *lwgeom = (char *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - char *result; - BOX2DFLOAT4 box; - unsigned char old_type; - int size; + char *lwgeom = (char *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + char *result; + BOX2DFLOAT4 box; + unsigned char old_type; + int size; //elog(NOTICE,"in LWGEOM_addBBOX"); - if (lwgeom_hasBBOX( (unsigned char) lwgeom[0] ) ) - { + if (lwgeom_hasBBOX( (unsigned char) lwgeom[0] ) ) + { //elog(NOTICE,"LWGEOM_addBBOX -- already has bbox"); - // easy - already has one. Just copy! - result = palloc ( *((int *) lwgeom)); - memcpy(result,lwgeom, *((int *) lwgeom)); - PG_RETURN_POINTER(result); - } + // easy - already has one. Just copy! + result = palloc ( *((int *) lwgeom)); + memcpy(result,lwgeom, *((int *) lwgeom)); + PG_RETURN_POINTER(result); + } //elog(NOTICE,"LWGEOM_addBBOX -- giving it a bbox"); - //construct new one - box = getbox2d(lwgeom+4); - old_type = (unsigned char) lwgeom[4]; + //construct new one + box = getbox2d(lwgeom+4); + old_type = (unsigned char) lwgeom[4]; - size = *((int *) lwgeom) +sizeof(BOX2DFLOAT4); + size = *((int *) lwgeom) +sizeof(BOX2DFLOAT4); - result = palloc ( size );// 16 for bbox2d + result = palloc ( size );// 16 for bbox2d - memcpy(result,&size,4); // size - result[4] = lwgeom_makeType_full( lwgeom_ndims(old_type), lwgeom_hasSRID(old_type), lwgeom_getType(old_type), 1); - memcpy(result+5, &box, sizeof(BOX2DFLOAT4)); // copy in bbox - memcpy(result+5+sizeof(BOX2DFLOAT4), lwgeom+5, *((int *) lwgeom) -5); // everything but the type and length + memcpy(result,&size,4); // size + result[4] = lwgeom_makeType_full( lwgeom_ndims(old_type), lwgeom_hasSRID(old_type), lwgeom_getType(old_type), 1); + memcpy(result+5, &box, sizeof(BOX2DFLOAT4)); // copy in bbox + memcpy(result+5+sizeof(BOX2DFLOAT4), lwgeom+5, *((int *) lwgeom) -5); // everything but the type and length - PG_RETURN_POINTER(result); + PG_RETURN_POINTER(result); } @@ -581,11 +579,17 @@ void elog_ERROR(const char* string) elog(ERROR,string); } -void *palloc_fn(size_t size) +static void free_fn(void *ptr) { - void * result; + //elog(NOTICE," pfree(%p)", ptr); + pfree(ptr); +} +static void *palloc_fn(size_t size) +{ + void * result; result = palloc(size); + //elog(NOTICE," palloc(%d) = %p", size, result); return result; } @@ -637,21 +641,20 @@ Datum parse_WKT_lwgeom(PG_FUNCTION_ARGS) char *parse_lwgeom_wkt(char *wkt_input) { - char *serialized_form = parse_lwg((const char *)wkt_input,(allocator) palloc_fn, (report_error)elog_ERROR); - + char *serialized_form = parse_lwg((const char *)wkt_input,(allocator) palloc_fn, (report_error)elog_ERROR); -//elog(NOTICE,"parse_lwgeom_wkt with %s",wkt_input); - if (serialized_form == NULL) - elog(ERROR,"parse_WKT:: couldnt parse!"); + //elog(NOTICE,"parse_lwgeom_wkt with %s",wkt_input); - return serialized_form; + if (serialized_form == NULL) + elog(ERROR,"parse_WKT:: couldnt parse!"); - // result = palloc( (*((int*) serialized_form))); - // memcpy(result, serialized_form, *((int*) serialized_form)); - // free(serialized_form); + return serialized_form; - // return result; + //result = palloc( (*((int*) serialized_form))); + //memcpy(result, serialized_form, *((int*) serialized_form)); + //free(serialized_form); + //return result; } diff --git a/lwgeom/lwpostgis.sql.in b/lwgeom/lwpostgis.sql.in index 226237a69..81a45bf08 100644 --- a/lwgeom/lwpostgis.sql.in +++ b/lwgeom/lwpostgis.sql.in @@ -11,6 +11,12 @@ -- -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- $Log$ +-- Revision 1.3 2004/08/20 14:08:41 strk +-- Added Geom{etry,}FromWkb(,[]) funx. +-- Added LWGEOM typedef and SERIALIZED_FORM(LWGEOM) macro. +-- Made lwgeom_setSRID an API function. +-- Added LWGEOM_setAllocator(). +-- -- Revision 1.2 2004/08/19 13:54:15 strk -- cpp checks updated to use 80 instead of 75 for USE_VERSION -- @@ -83,6 +89,33 @@ CREATE TYPE geometry ( storage = main ); +CREATEFUNCTION geometryfromtext(geometry) + RETURNS geometry + AS '@MODULE_FILENAME@','LWGEOM_from_text' + LANGUAGE 'C' WITH (isstrict,iscachable); + +CREATEFUNCTION geometryfromtext(geometry, int4) + RETURNS geometry + AS '@MODULE_FILENAME@','LWGEOM_from_text' + LANGUAGE 'C' WITH (isstrict,iscachable); + +CREATEFUNCTION geomfromtext(geometry) +RETURNS geometry AS ' +SELECT geometryfromtext($1) +' LANGUAGE 'SQL' WITH (isstrict,iscachable); + +CREATEFUNCTION geomfromtext(geometry, int4) +RETURNS geometry AS ' +SELECT geometryfromtext($1, $2) +' LANGUAGE 'SQL' WITH (isstrict,iscachable); + + +----------------------------------------------------------------------- +-- +-- BOX2D +-- +----------------------------------------------------------------------- + CREATEFUNCTION box2d_in(cstring) RETURNS box2d AS '@MODULE_FILENAME@','BOX2DFLOAT4_in' -- 2.40.0