#include #include #include #include "lwgeom_pg.h" #include "liblwgeom.h" //#define DEBUG_CALLS 1 LWGEOM * lwgeom_deserialize(char *srl) { int type = lwgeom_getType(srl[0]); switch (type) { case POINTTYPE: return (LWGEOM *)lwpoint_deserialize(srl); case LINETYPE: return (LWGEOM *)lwline_deserialize(srl); case POLYGONTYPE: return (LWGEOM *)lwpoly_deserialize(srl); case MULTIPOINTTYPE: return (LWGEOM *)lwmpoint_deserialize(srl); case MULTILINETYPE: return (LWGEOM *)lwmline_deserialize(srl); case MULTIPOLYGONTYPE: return (LWGEOM *)lwmpoly_deserialize(srl); case COLLECTIONTYPE: return (LWGEOM *)lwcollection_deserialize(srl); default: lwerror("Unknown geometry type: %d", type); return NULL; } } size_t lwgeom_serialize_size(LWGEOM *lwgeom) { int type = lwgeom->type; #ifdef DEBUG_CALLS lwnotice("lwgeom_serialize_size called"); #endif switch (type) { case POINTTYPE: return lwpoint_serialize_size((LWPOINT *)lwgeom); case LINETYPE: return lwline_serialize_size((LWLINE *)lwgeom); case POLYGONTYPE: return lwpoly_serialize_size((LWPOLY *)lwgeom); case MULTIPOINTTYPE: case MULTILINETYPE: case MULTIPOLYGONTYPE: case COLLECTIONTYPE: return lwcollection_serialize_size((LWCOLLECTION *)lwgeom); default: lwerror("Unknown geometry type: %d", type); return 0; } } void lwgeom_serialize_buf(LWGEOM *lwgeom, char *buf, size_t *retsize) { int type = lwgeom->type; #ifdef DEBUG_CALLS lwnotice("lwgeom_serialize_buf called with a %s", lwgeom_typename(type)); #endif switch (type) { case POINTTYPE: lwpoint_serialize_buf((LWPOINT *)lwgeom, buf, retsize); break; case LINETYPE: lwline_serialize_buf((LWLINE *)lwgeom, buf, retsize); break; case POLYGONTYPE: lwpoly_serialize_buf((LWPOLY *)lwgeom, buf, retsize); break; case MULTIPOINTTYPE: case MULTILINETYPE: case MULTIPOLYGONTYPE: case COLLECTIONTYPE: lwcollection_serialize_buf((LWCOLLECTION *)lwgeom, buf, retsize); break; default: lwerror("Unknown geometry type: %d", type); return; } return; } char * lwgeom_serialize(LWGEOM *lwgeom) { size_t size = lwgeom_serialize_size(lwgeom); size_t retsize; char *serialized = lwalloc(size); lwgeom_serialize_buf(lwgeom, serialized, &retsize); #ifdef DEBUG if ( retsize != size ) { lwerror("lwgeom_serialize: computed size %d, returned size %d", size, retsize); } #endif return serialized; } // Force Right-hand-rule on LWGEOM polygons void lwgeom_forceRHR(LWGEOM *lwgeom) { LWCOLLECTION *coll; int i; switch (lwgeom->type) { case POLYGONTYPE: lwpoly_reverse((LWPOLY *)lwgeom); return; case MULTIPOLYGONTYPE: case COLLECTIONTYPE: coll = (LWCOLLECTION *)lwgeom; for (i=0; ingeoms; i++) lwgeom_forceRHR(coll->geoms[i]); return; } } // Reverse vertex order of LWGEOM void lwgeom_reverse(LWGEOM *lwgeom) { int i; LWCOLLECTION *col; switch (lwgeom->type) { case LINETYPE: lwline_reverse((LWLINE *)lwgeom); return; case POLYGONTYPE: lwpoly_reverse((LWPOLY *)lwgeom); return; case MULTILINETYPE: case MULTIPOLYGONTYPE: case COLLECTIONTYPE: col = (LWCOLLECTION *)lwgeom; for (i=0; ingeoms; i++) lwgeom_reverse(col->geoms[i]); return; } } int lwgeom_compute_bbox_p(LWGEOM *lwgeom, BOX2DFLOAT4 *buf) { switch(lwgeom->type) { case POINTTYPE: return lwpoint_compute_bbox_p((LWPOINT *)lwgeom, buf); case LINETYPE: return lwline_compute_bbox_p((LWLINE *)lwgeom, buf); case POLYGONTYPE: return lwpoly_compute_bbox_p((LWPOLY *)lwgeom, buf); case MULTIPOINTTYPE: case MULTILINETYPE: case MULTIPOLYGONTYPE: case COLLECTIONTYPE: return lwcollection_compute_bbox_p((LWCOLLECTION *)lwgeom, buf); } return 0; } //dont forget to lwfree() result BOX2DFLOAT4 * lwgeom_compute_bbox(LWGEOM *lwgeom) { BOX2DFLOAT4 *result = lwalloc(sizeof(BOX2DFLOAT4)); if ( lwgeom_compute_bbox_p(lwgeom, result) ) return result; else return NULL; } LWPOINT * lwgeom_as_lwpoint(LWGEOM *lwgeom) { if ( lwgeom->type == POINTTYPE ) return (LWPOINT *)lwgeom; else return NULL; } LWLINE * lwgeom_as_lwline(LWGEOM *lwgeom) { if ( lwgeom->type == LINETYPE ) return (LWLINE *)lwgeom; else return NULL; } LWPOLY * lwgeom_as_lwpoly(LWGEOM *lwgeom) { if ( lwgeom->type == POLYGONTYPE ) return (LWPOLY *)lwgeom; else return NULL; } LWCOLLECTION * lwgeom_as_lwcollection(LWGEOM *lwgeom) { if ( lwgeom->type >= MULTIPOINTTYPE ) return (LWCOLLECTION *)lwgeom; else return NULL; } LWMPOINT * lwgeom_as_lwmpoint(LWGEOM *lwgeom) { if ( lwgeom->type == MULTIPOINTTYPE ) return (LWMPOINT *)lwgeom; else return NULL; } LWMLINE * lwgeom_as_lwmline(LWGEOM *lwgeom) { if ( lwgeom->type == MULTILINETYPE ) return (LWMLINE *)lwgeom; else return NULL; } LWMPOLY * lwgeom_as_lwmpoly(LWGEOM *lwgeom) { if ( lwgeom->type == MULTIPOLYGONTYPE ) return (LWMPOLY *)lwgeom; else return NULL; } LWGEOM *lwmpoly_as_lwgeom(LWMPOLY *obj) { return (LWGEOM *)obj; } LWGEOM *lwmline_as_lwgeom(LWMLINE *obj) { return (LWGEOM *)obj; } LWGEOM *lwmpoint_as_lwgeom(LWMPOINT *obj) { return (LWGEOM *)obj; } LWGEOM *lwcollection_as_lwgeom(LWCOLLECTION *obj) { return (LWGEOM *)obj; } LWGEOM *lwpoly_as_lwgeom(LWPOLY *obj) { return (LWGEOM *)obj; } LWGEOM *lwline_as_lwgeom(LWLINE *obj) { return (LWGEOM *)obj; } LWGEOM *lwpoint_as_lwgeom(LWPOINT *obj) { return (LWGEOM *)obj; } void lwgeom_release(LWGEOM *lwgeom) { uint32 i; LWCOLLECTION *col; // Collection if ( (col=lwgeom_as_lwcollection(lwgeom)) ) { for (i=0; ingeoms; i++) { lwgeom_release(col->geoms[i]); } lwfree(lwgeom); } // Single element else lwfree(lwgeom); } // Clone an LWGEOM object. POINTARRAY are not copied. LWGEOM * lwgeom_clone(const LWGEOM *lwgeom) { switch(lwgeom->type) { case POINTTYPE: return (LWGEOM *)lwpoint_clone((LWPOINT *)lwgeom); case LINETYPE: return (LWGEOM *)lwline_clone((LWLINE *)lwgeom); case POLYGONTYPE: return (LWGEOM *)lwpoly_clone((LWPOLY *)lwgeom); case MULTIPOINTTYPE: case MULTILINETYPE: case MULTIPOLYGONTYPE: case COLLECTIONTYPE: return (LWGEOM *)lwcollection_clone((LWCOLLECTION *)lwgeom); default: return NULL; } } // Add 'what' to 'to' at position 'where'. // where=0 == prepend // where=-1 == append // Appended-to LWGEOM gets a new type based on new condition. // Mix of dimensions is not allowed (TODO: allow it?). LWGEOM * lwgeom_add(const LWGEOM *to, uint32 where, const LWGEOM *what) { if ( what->ndims != to->ndims ) { lwerror("lwgeom_add: mixed dimensions not supported"); return NULL; } switch(to->type) { case POINTTYPE: return (LWGEOM *)lwpoint_add((const LWPOINT *)to, where, what); case LINETYPE: return (LWGEOM *)lwline_add((const LWLINE *)to, where, what); case POLYGONTYPE: return (LWGEOM *)lwpoly_add((const LWPOLY *)to, where, what); case MULTIPOINTTYPE: case MULTILINETYPE: case MULTIPOLYGONTYPE: return (LWGEOM *)lwcollection_add((const LWCOLLECTION *)to, where, what); default: return NULL; } }