From d349b26fe03efa64a88651b9bc0985f1f2fa59ae Mon Sep 17 00:00:00 2001 From: Sandro Santilli Date: Tue, 14 Sep 2004 12:31:31 +0000 Subject: [PATCH] CHIP and GEOS types (forgot to add) git-svn-id: http://svn.osgeo.org/postgis/trunk@821 b70326c6-7e19-0410-871a-916f4a2858ee --- lwgeom/lwgeom_chip.c | 291 ++++++ lwgeom/lwgeom_geos_wrapper.cpp | 1511 ++++++++++++++++++++++++++++++++ 2 files changed, 1802 insertions(+) create mode 100644 lwgeom/lwgeom_chip.c create mode 100644 lwgeom/lwgeom_geos_wrapper.cpp diff --git a/lwgeom/lwgeom_chip.c b/lwgeom/lwgeom_chip.c new file mode 100644 index 000000000..a8dcc93df --- /dev/null +++ b/lwgeom/lwgeom_chip.c @@ -0,0 +1,291 @@ + +#include +#include +#include +#include +#include + +#include "postgres.h" +#include "access/gist.h" +#include "access/itup.h" +#include "access/rtree.h" +#include "fmgr.h" +#include "utils/elog.h" + +#include "lwgeom.h" + +// External functions (what's again the reason for using explicit hex form ?) +extern void deparse_hex(unsigned char str, unsigned char *result); +extern unsigned char parse_hex(char *str); + +// Internal funcs +void swap_char(char *a,char *b); +void flip_endian_double(char *d); +void flip_endian_int32(char *i); + + +// Prototypes +Datum CHIP_in(PG_FUNCTION_ARGS); +Datum CHIP_out(PG_FUNCTION_ARGS); +Datum CHIP_to_LWGEOM(PG_FUNCTION_ARGS); +Datum CHIP_getSRID(PG_FUNCTION_ARGS); +Datum CHIP_getFactor(PG_FUNCTION_ARGS); +Datum CHIP_setFactor(PG_FUNCTION_ARGS); +Datum CHIP_getDatatype(PG_FUNCTION_ARGS); +Datum CHIP_getCompression(PG_FUNCTION_ARGS); +Datum CHIP_getHeight(PG_FUNCTION_ARGS); +Datum CHIP_getWidth(PG_FUNCTION_ARGS); +Datum CHIP_setSRID(PG_FUNCTION_ARGS); + + +// input is a string with hex chars in it. Convert to binary and put in the result +PG_FUNCTION_INFO_V1(CHIP_in); +Datum CHIP_in(PG_FUNCTION_ARGS) +{ + char *str = PG_GETARG_CSTRING(0); + CHIP *result; + int size; + int t; + int input_str_len; + int datum_size; + +//printf("chip_in called\n"); + + input_str_len = strlen(str); + + if ( ( ( (int)(input_str_len/2.0) ) *2.0) != input_str_len) + { + elog(ERROR,"CHIP_in parser - should be even number of characters!"); + PG_RETURN_NULL(); + } + + if (strspn(str,"0123456789ABCDEF") != strlen(str) ) + { + elog(ERROR,"CHIP_in parser - input contains bad characters. Should only have '0123456789ABCDEF'!"); + PG_RETURN_NULL(); + } + size = (input_str_len/2) ; + result = (CHIP *) palloc(size); + + for (t=0;tsize = size; + if (result->size < sizeof(CHIP) ) + { + elog(ERROR,"CHIP_in parser - bad data (too small to be a CHIP)!"); + PG_RETURN_NULL(); + } + + if (result->endian_hint != 1) + { + //need to do an endian flip + flip_endian_int32( (char *) &result->endian_hint); + + flip_endian_double((char *) &result->bvol.xmin); + flip_endian_double((char *) &result->bvol.ymin); + flip_endian_double((char *) &result->bvol.zmin); + + flip_endian_double((char *) &result->bvol.xmax); + flip_endian_double((char *) &result->bvol.ymax); + flip_endian_double((char *) &result->bvol.zmax); + + flip_endian_int32( (char *) & result->SRID); + //dont know what to do with future[8] ... + + flip_endian_int32( (char *) & result->height); + flip_endian_int32( (char *) & result->width); + flip_endian_int32( (char *) & result->compression); + flip_endian_int32( (char *) & result->factor); + flip_endian_int32( (char *) & result->datatype); + + } + if (result->endian_hint != 1 ) + { + elog(ERROR,"CHIP_in parser - bad data (endian flag != 1)!"); + PG_RETURN_NULL(); + } + datum_size = 4; + + if ( (result->datatype == 6) || (result->datatype == 7) || (result->datatype == 106) || (result->datatype == 107) ) + { + datum_size = 2; + } + if ( (result->datatype == 8) || (result->datatype == 108) ) + { + datum_size=1; + } + + if (result->compression ==0) //only true for non-compressed data + { + if (result->size != (sizeof(CHIP) + datum_size * result->width*result->height) ) + { + elog(ERROR,"CHIP_in parser - bad data (actual size != computed size)!"); + PG_RETURN_NULL(); + } + } + + PG_RETURN_POINTER(result); +} + + +//given a CHIP structure, convert it to Hex and put it in a string +PG_FUNCTION_INFO_V1(CHIP_out); +Datum CHIP_out(PG_FUNCTION_ARGS) +{ + CHIP *chip = (CHIP *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + char *result; + int size_result; + int t; + +//printf("chip_out called\n"); + + size_result = (chip->size ) *2 +1; // +1 for null char + result = palloc (size_result); + result[size_result-1] = 0; //null terminate + + for (t=0; t< (chip->size); t++) + { + deparse_hex( ((unsigned char *) chip)[t], &result[t*2]); + } + PG_RETURN_CSTRING(result); +} + + + +PG_FUNCTION_INFO_V1(CHIP_to_LWGEOM); +Datum CHIP_to_LWGEOM(PG_FUNCTION_ARGS) +{ + CHIP *chip = (CHIP *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + LWGEOM *result; + POINT2D *pts = palloc(sizeof(POINT2D)*5); + POINTARRAY *pa[1]; + LWPOLY *poly; + char *ser; + int wantbbox = false; + + // Assign coordinates to POINT2D array + pts[0].x = chip->bvol.xmin; pts[0].y = chip->bvol.ymin; + pts[1].x = chip->bvol.xmin; pts[1].y = chip->bvol.ymax; + pts[2].x = chip->bvol.xmax; pts[2].y = chip->bvol.ymax; + pts[3].x = chip->bvol.xmax; pts[3].y = chip->bvol.ymin; + pts[4].x = chip->bvol.xmin; pts[4].y = chip->bvol.ymin; + + // Construct point array + pa[0] = palloc(sizeof(POINTARRAY)); + pa[0]->serialized_pointlist = (char *)pts; + pa[0]->ndims = 2; + pa[0]->npoints = 5; + + // Construct polygon + poly = lwpoly_construct(2, chip->SRID, 1, pa); + + // Serialize polygon + ser = lwpoly_serialize(poly); + + // Construct LWGEOM + result = LWGEOM_construct(ser, chip->SRID, wantbbox); + + PG_RETURN_POINTER(result); + +} + +PG_FUNCTION_INFO_V1(CHIP_getSRID); +Datum CHIP_getSRID(PG_FUNCTION_ARGS) +{ + CHIP *c = (CHIP *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + PG_RETURN_INT32(c->SRID); +} + +PG_FUNCTION_INFO_V1(CHIP_getFactor); +Datum CHIP_getFactor(PG_FUNCTION_ARGS) +{ + CHIP *c = (CHIP *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + PG_RETURN_FLOAT4(c->factor); +} + +PG_FUNCTION_INFO_V1(CHIP_setFactor); +Datum CHIP_setFactor(PG_FUNCTION_ARGS) +{ + CHIP *c = (CHIP *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + float factor = PG_GETARG_FLOAT4(1); + CHIP *result; + + result = (CHIP *) palloc(c->size); + + memcpy(result,c,c->size); + result->factor = factor; + + PG_RETURN_POINTER(result); +} + + + +PG_FUNCTION_INFO_V1(CHIP_getDatatype); +Datum CHIP_getDatatype(PG_FUNCTION_ARGS) +{ + CHIP *c = (CHIP *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + PG_RETURN_INT32(c->datatype); +} + +PG_FUNCTION_INFO_V1(CHIP_getCompression); +Datum CHIP_getCompression(PG_FUNCTION_ARGS) +{ + CHIP *c = (CHIP *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + PG_RETURN_INT32(c->compression); +} + +PG_FUNCTION_INFO_V1(CHIP_getHeight); +Datum CHIP_getHeight(PG_FUNCTION_ARGS) +{ + CHIP *c = (CHIP *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + PG_RETURN_INT32(c->height); +} + +PG_FUNCTION_INFO_V1(CHIP_getWidth); +Datum CHIP_getWidth(PG_FUNCTION_ARGS) +{ + CHIP *c = (CHIP *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + PG_RETURN_INT32(c->width); +} + + +PG_FUNCTION_INFO_V1(CHIP_setSRID); +Datum CHIP_setSRID(PG_FUNCTION_ARGS) +{ + CHIP *c = (CHIP *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + int32 new_srid = PG_GETARG_INT32(1); + CHIP *result; + + result = (CHIP *) palloc(c->size); + + memcpy(result, c, c->size); + result->SRID = new_srid; + + PG_RETURN_POINTER(result); +} + +void flip_endian_double(char *d) +{ + swap_char(d+7, d); + swap_char(d+6, d+1); + swap_char(d+5, d+2); + swap_char(d+4, d+3); +} + +void swap_char(char *a,char *b) +{ + char c; + + c = *a; + *a=*b; + *b=c; +} + +void flip_endian_int32(char *i) +{ + swap_char (i+3,i); + swap_char (i+2,i+1); +} diff --git a/lwgeom/lwgeom_geos_wrapper.cpp b/lwgeom/lwgeom_geos_wrapper.cpp new file mode 100644 index 000000000..7aa09dcb4 --- /dev/null +++ b/lwgeom/lwgeom_geos_wrapper.cpp @@ -0,0 +1,1511 @@ +// g++ postgis_GEOSwrapper.cpp -c -I/usr/local/include -I/usr/local/include/geos -I/usr/local/src/postgresql-7.2.3//src/include + +#include + +#include +#include +#include + +#include "../postgis_geos_version.h" +#include "geos/geom.h" +#include "geos/util.h" + +using namespace geos; + +//WARNING THIS *MUST* BE SET CORRECTLY. +int MAXIMUM_ALIGNOF = -999999; // to be set during initialization - this will be either 4 (intel) or 8 (sparc) + +//for getting things to align properly double are on 8byte align on solaris machines, and 4bytes on intel + +#define TYPEALIGN(ALIGNVAL,LEN) (((long)(LEN) + (ALIGNVAL-1)) & ~(ALIGNVAL-1)) +#define MAXALIGN(LEN) TYPEALIGN(MAXIMUM_ALIGNOF, (LEN)) + +typedef int int32; + + +//---- Definitions found in lwgeom.h (and postgis) + +typedef unsigned int uint32; +typedef int int32; + +typedef struct +{ + double xmin, ymin, zmin; + double xmax, ymax, zmax; +} BOX3D; + +typedef struct { double x,y,z; } POINT3D; + +typedef struct +{ + char *serialized_pointlist; + char ndims; + uint32 npoints; +} POINTARRAY; + +typedef struct +{ + char ndims; + int SRID; + POINTARRAY *point; +} LWPOINT; // "light-weight point" + +typedef struct +{ + char ndims; + int SRID; + POINTARRAY *points; +} LWLINE; + +typedef struct +{ + int32 SRID; + char ndims; + int nrings; + POINTARRAY **rings; +} LWPOLY; + +extern "C" char *getPoint(POINTARRAY *pa, int n); + +//---- End of definitions found in lwgeom.h + +#define POINTTYPE 1 +#define LINETYPE 2 +#define POLYGONTYPE 3 +#define MULTIPOINTTYPE 4 +#define MULTILINETYPE 5 +#define MULTIPOLYGONTYPE 6 +#define COLLECTIONTYPE 7 + +//########################################################### + +extern "C" char *GEOSrelate(Geometry *g1, Geometry*g2); +extern "C" void initGEOS(int maxalign); + + +extern "C" void GEOSdeleteChar(char *a); +extern "C" void GEOSdeleteGeometry(Geometry *a); +extern "C" char GEOSrelatePattern(Geometry *g1, Geometry*g2,char *pat); +extern "C" char GEOSrelateDisjoint(Geometry *g1, Geometry*g2); +extern "C" char GEOSrelateTouches(Geometry *g1, Geometry*g2); +extern "C" char GEOSrelateIntersects(Geometry *g1, Geometry*g2); +extern "C" char GEOSrelateCrosses(Geometry *g1, Geometry*g2); +extern "C" char GEOSrelateWithin(Geometry *g1, Geometry*g2); +extern "C" char GEOSrelateContains(Geometry *g1, Geometry*g2); +extern "C" char GEOSrelateOverlaps(Geometry *g1, Geometry*g2); +extern "C" char *GEOSversion(); +extern "C" char *GEOSjtsport(); + +extern "C" Geometry *PostGIS2GEOS_point(const LWPOINT *point); +extern "C" Geometry *PostGIS2GEOS_linestring(const LWLINE *line); +extern "C" Geometry *PostGIS2GEOS_polygon(const LWPOLY *polygon); +extern "C" Geometry *PostGIS2GEOS_multipolygon(LWPOLY *const *const geoms, uint32 ngeoms, int SRID, int is3d); +extern "C" Geometry *PostGIS2GEOS_multilinestring(LWLINE *const *const geoms, uint32 ngeoms, int SRID, int is3d); +extern "C" Geometry *PostGIS2GEOS_multipoint(LWPOINT *const *const geoms, uint32 ngeoms, int SRID, int is3d); +extern "C" Geometry *PostGIS2GEOS_collection(Geometry **geoms, int ngeoms, int SRID, bool is3d); +extern "C" Geometry *PostGIS2GEOS_box3d(BOX3D *box, int SRID); + +extern "C" char GEOSisvalid(Geometry *g1); + + +extern "C" char *GEOSasText(Geometry *g1); +extern "C" char GEOSisEmpty(Geometry *g1); +extern "C" char *GEOSGeometryType(Geometry *g1); +extern "C" int GEOSGeometryTypeId(Geometry *g1); + + +extern "C" char *throw_exception(Geometry *g); + +extern "C" Geometry *GEOSIntersection(Geometry *g1,Geometry *g1); +extern "C" Geometry *GEOSBuffer(Geometry *g1,double width); +extern "C" Geometry *GEOSConvexHull(Geometry *g1); +extern "C" Geometry *GEOSDifference(Geometry *g1,Geometry *g2); +extern "C" Geometry *GEOSBoundary(Geometry *g1); +extern "C" Geometry *GEOSSymDifference(Geometry *g1,Geometry *g2); +extern "C" Geometry *GEOSUnion(Geometry *g1,Geometry *g2); + + +extern "C" POINT3D *GEOSGetCoordinate(Geometry *g1); +extern "C" POINT3D *GEOSGetCoordinates_Polygon(Polygon *g1); +extern "C" POINT3D *GEOSGetCoordinates(Geometry *g1); +extern "C" int GEOSGetNumCoordinate(Geometry *g1); +extern "C" const Geometry *GEOSGetGeometryN(Geometry *g1, int n); +extern "C" const Geometry *GEOSGetExteriorRing(Geometry *g1); +extern "C" const Geometry *GEOSGetInteriorRingN(Geometry *g1, int n); +extern "C" int GEOSGetNumInteriorRings(Geometry *g1); +extern "C" int GEOSGetSRID(Geometry *g1); +extern "C" int GEOSGetNumGeometries(Geometry *g1); + +extern "C" char GEOSisSimple(Geometry *g1); +extern "C" char GEOSequals(Geometry *g1, Geometry*g2); + +extern "C" char GEOSisRing(Geometry *g1); + +extern "C" Geometry *GEOSpointonSurface(Geometry *g1); + +extern "C" Geometry *GEOSGetCentroid(Geometry *g1); + +extern "C" void NOTICE_MESSAGE(char *msg); + + + +//########################################################### +#if GEOS_LAST_INTERFACE < 2 +# define CoordinateSequence CoordinateList +# define DefaultCoordinateSequence BasicCoordinateList +#endif + +GeometryFactory *geomFactory = NULL; + + +void initGEOS (int maxalign) +{ + if (geomFactory == NULL) + { + geomFactory = new GeometryFactory( new PrecisionModel(), -1); // NOTE: SRID will have to be changed after geometry creation + MAXIMUM_ALIGNOF = maxalign; + } +} + +// ------------------------------------------------------------------------------ +// geometry constuctors - return NULL if there was an error +//------------------------------------------------------------------------------- + + +//note: you lose the 3d from this! +Geometry *PostGIS2GEOS_box3d(BOX3D *box, int SRID) +{ + DefaultCoordinateSequence *cl = new DefaultCoordinateSequence(5); + try { + Geometry *g; + Coordinate c; + c.x = box->xmin; c.y = box->ymin; + cl->setAt(c, 0); + c.x = box->xmin; c.y = box->ymax; + cl->setAt(c, 1); + c.x = box->xmax; c.y = box->ymax; + cl->setAt(c, 2); + c.x = box->xmax; c.y = box->ymin; + cl->setAt(c, 3); + c.x = box->xmin; c.y = box->ymin; + cl->setAt(c, 4); + + g = geomFactory->createLinearRing(cl); +#if GEOS_LAST_INTERFACE < 2 + delete cl; +#endif + if (g==NULL) return NULL; + g->setSRID(SRID); + return g; + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete cl; + return NULL; + } + catch (...) + { + delete cl; + return NULL; + } +} + +Geometry *PostGIS2GEOS_point(const LWPOINT *lwpoint) +{ + POINT3D *point = (POINT3D *)getPoint(lwpoint->point, 0); + int SRID = lwpoint->SRID; + bool is3d = lwpoint->point->ndims > 2 ? 1 : 0; + try + { + Coordinate *c; + + if (is3d) + c = new Coordinate(point->x, point->y); + else + c = new Coordinate(point->x, point->y, point->z); + Geometry *g = geomFactory->createPoint(*c); + delete c; + if (g==NULL) + return NULL; + g->setSRID(SRID); + return g; + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return NULL; + } + + catch (...) + { + return NULL; + } +} + +/* + * This function must return an all-new allocated object + */ +Geometry * +PostGIS2GEOS_linestring(const LWLINE *lwline) +{ + POINTARRAY *pa = lwline->points; + bool is3d = pa->ndims > 2 ? 1 : 0; + int SRID = lwline->SRID; + + try{ + uint32 t; + Coordinate c; + POINT3D *p; + + //build coordinatelist & pre-allocate space + DefaultCoordinateSequence *coords = new DefaultCoordinateSequence(pa->npoints); + if (is3d) + { + for (t=0; tnpoints; t++) + { + p = (POINT3D *)getPoint(pa, t); + c.x = p->x; + c.y = p->y; + c.z = p->z; + coords->setAt(c ,t); + } + } + else //make 2d points + { + for (t=0; tnpoints; t++) + { + p = (POINT3D *)getPoint(pa, t); + c.x = p->x; + c.y = p->y; + c.z = DoubleNotANumber; + coords->setAt(c ,t); + } + } + Geometry *g = geomFactory->createLineString(coords); +#if GEOS_LAST_INTERFACE < 2 + delete coords; +#endif + if (g==NULL) return NULL; + g->setSRID(SRID); + return g; + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return NULL; + } + + catch (...) + { + return NULL; + } +} + +Geometry *PostGIS2GEOS_polygon(const LWPOLY *lwpoly) +{ + POINTARRAY *pa; + int SRID = lwpoly->SRID; + bool is3d = lwpoly->ndims > 2 ? 1 : 0; + + try + { + Coordinate c; + uint32 t; + int ring; + Geometry *g; + LinearRing *outerRing; + LinearRing *innerRing; + DefaultCoordinateSequence *cl; + POINT3D *p; + vector *innerRings=new vector; + + // make outerRing + pa = lwpoly->rings[0]; + cl = new DefaultCoordinateSequence(pa->npoints); + if (is3d) + { + for(t=0; tnpoints; t++) + { + p = (POINT3D *)getPoint(pa, t); + c.x = p->x; + c.y = p->y; + c.z = p->z; + cl->setAt( c ,t); + } + } + else + { + for(t=0; tnpoints; t++) + { + p = (POINT3D *)getPoint(pa, t); + c.x = p->x; + c.y = p->y; + c.z = DoubleNotANumber; + cl->setAt(c ,t); + } + } + outerRing = (LinearRing*) geomFactory->createLinearRing(cl); +#if GEOS_LAST_INTERFACE < 2 + delete cl; +#endif + if (outerRing == NULL) return NULL; + outerRing->setSRID(SRID); + + for(ring=1; ringnrings; ring++) + { + pa = lwpoly->rings[ring]; + cl = new DefaultCoordinateSequence(pa->npoints); + if (is3d) + { + for(t=0; tnpoints; t++) + { + p = (POINT3D *)getPoint(pa, t); + c.x = p->x; + c.y = p->y; + c.z = p->z; + cl->setAt(c ,t); + } + } + else + { + for(t=0; tnpoints; t++) + { + p = (POINT3D *)getPoint(pa, t); + c.x = p->x; + c.y = p->y; + c.z = DoubleNotANumber; + cl->setAt(c ,t); + } + } + innerRing = (LinearRing *) geomFactory->createLinearRing(cl); +#if GEOS_LAST_INTERFACE < 2 + delete cl; +#endif + if (innerRing == NULL) + { + delete outerRing; + return NULL; + } + innerRing->setSRID(SRID); + innerRings->push_back(innerRing); + } + + g = geomFactory->createPolygon(outerRing, innerRings); + if (g==NULL) return NULL; + g->setSRID(SRID); + return g; + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return NULL; + } + + catch (...) + { + return NULL; + } +} + +Geometry *PostGIS2GEOS_multipoint(LWPOINT *const *const geoms, uint32 ngeoms, int SRID, bool is3d) +{ + try + { + uint32 t; + vector *subGeoms=NULL; + Geometry *g; + + subGeoms=new vector; + + for (t=0; tpush_back(PostGIS2GEOS_point(geoms[t])); + } + g = geomFactory->createMultiPoint(subGeoms); +#if GEOS_LAST_INTERFACE < 2 + delete subGeoms; +#endif + + if (g== NULL) + return NULL; + g->setSRID(SRID); + return g; + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return NULL; + } + + catch (...) + { + return NULL; + } +} + +Geometry *PostGIS2GEOS_multilinestring(LWLINE *const *const geoms, uint32 ngeoms, int SRID, bool is3d) +{ + try + { + uint32 t; + vector *subGeoms=NULL; + Geometry *g; + + subGeoms=new vector; + + for (t=0; tpush_back(PostGIS2GEOS_linestring(geoms[t])); + } + g = geomFactory->createMultiLineString(subGeoms); +#if GEOS_LAST_INTERFACE < 2 + delete subGeoms; +#endif + + if (g== NULL) + return NULL; + g->setSRID(SRID); + return g; + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return NULL; + } + + catch (...) + { + return NULL; + } +} + +Geometry *PostGIS2GEOS_multipolygon(LWPOLY *const *const polygons, uint32 npolys, int SRID, bool is3d) +{ + try + { + uint32 t; + vector *subPolys=NULL; + Geometry *g; + + subPolys=new vector; + + for (t =0; t< npolys; t++) + { + subPolys->push_back(PostGIS2GEOS_polygon(polygons[t])); + } + g = geomFactory->createMultiPolygon(subPolys); +#if GEOS_LAST_INTERFACE < 2 + delete subPolys; +#endif + + if (g== NULL) + return NULL; + g->setSRID(SRID); + return g; + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return NULL; + } + + catch (...) + { + return NULL; + } +} + +Geometry *PostGIS2GEOS_collection(Geometry **geoms, int ngeoms, int SRID, bool is3d) +{ + try + { + Geometry *g; + int t; + vector *subGeos=new vector; + + for (t =0; t< ngeoms; t++) + { + subGeos->push_back(geoms[t]); + } + g = geomFactory->buildGeometry(subGeos); +#if GEOS_LAST_INTERFACE < 2 + delete subGeos; +#endif + if (g==NULL) + return NULL; + g->setSRID(SRID); + return g; + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return NULL; + } + + catch (...) + { + return NULL; + } +} + + +//----------------------------------------------------------- +// relate()-related functions +// return 0 = false, 1 = true, 2 = error occured +//----------------------------------------------------------- + +char GEOSrelateDisjoint(Geometry *g1, Geometry*g2) +{ + try { + bool result; + result = g1->disjoint(g2); + return result; + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return 2; + } + catch (...) + { + return 2; + } +} + +char GEOSrelateTouches(Geometry *g1, Geometry*g2) +{ + try { + bool result; + result = g1->touches(g2); + return result; + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return 2; + } + + catch (...) + { + return 2; + } +} + +char GEOSrelateIntersects(Geometry *g1, Geometry*g2) +{ + try { + bool result; + result = g1->intersects(g2); + return result; + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return 2; + } + + catch (...) + { + return 2; + } +} + +char GEOSrelateCrosses(Geometry *g1, Geometry*g2) +{ + try { + bool result; + result = g1->crosses(g2); + return result; + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return 2; + } + + catch (...) + { + return 2; + } +} + +char GEOSrelateWithin(Geometry *g1, Geometry*g2) +{ + try { + bool result; + result = g1->within(g2); + return result; + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return 2; + } + + catch (...) + { + return 2; + } +} + +// call g1->contains(g2) +// returns 0 = false +// 1 = true +// 2 = error was trapped +char GEOSrelateContains(Geometry *g1, Geometry*g2) +{ + try { + bool result; + result = g1->contains(g2); + return result; + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return 2; + } + + catch (...) + { + return 2; + } +} + +char GEOSrelateOverlaps(Geometry *g1, Geometry*g2) +{ + try { + bool result; + result = g1->overlaps(g2); + return result; + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return 2; + } + + catch (...) + { + return 2; + } +} + + +//------------------------------------------------------------------- +// low-level relate functions +//------------------------------------------------------------------ + +char GEOSrelatePattern(Geometry *g1, Geometry*g2,char *pat) +{ + try { + bool result; + string s = pat; + result = g1->relate(g2,pat); + return result; + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return 2; + } + + catch (...) + { + return 2; + } +} + +char *GEOSrelate(Geometry *g1, Geometry*g2) +{ + + try { + + IntersectionMatrix *im = g1->relate(g2); + + string s; + char *result; + if (im == NULL) + return NULL; + + s= im->toString(); + result = (char*) malloc( s.length() + 1); + strcpy(result, s.c_str() ); + + return result; + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return NULL; + } + + catch (...) + { + return NULL; + } +} + + + +//----------------------------------------------------------------- +// isValid +//----------------------------------------------------------------- + + +char GEOSisvalid(Geometry *g1) +{ + try { + bool result; + result =g1->isValid(); + return result; + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return 2; + } + + catch (...) + { + return 2; + } + +} + + +//----------------------------------------------------------------- +// general purpose +//----------------------------------------------------------------- + +char GEOSequals(Geometry *g1, Geometry*g2) +{ + try { + bool result; + result = g1->equals(g2); + return result; + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return 2; + } + + catch (...) + { + return 2; + } +} + + + +char *GEOSasText(Geometry *g1) +{ + try + { + string s = g1->toString(); + + + char *result; + result = (char*) malloc( s.length() + 1); + strcpy(result, s.c_str() ); + return result; + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return NULL; + } + + catch (...) + { + return NULL; + } +} + +char GEOSisEmpty(Geometry *g1) +{ + try + { + return g1->isEmpty(); + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return 2; + } + + catch (...) + { + return 2; + } +} + +char GEOSisSimple(Geometry *g1) +{ + try + { + return g1->isSimple(); + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return 2; + } + + catch (...) + { + return 2; + } +} + +char GEOSisRing(Geometry *g1) +{ + try + { + return (( (LinearRing*)g1)->isRing()); + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return 2; + } + + catch (...) + { + return 2; + } +} + + + +//free the result of this +char *GEOSGeometryType(Geometry *g1) +{ + try + { + string s = g1->getGeometryType(); + + + char *result; + result = (char*) malloc( s.length() + 1); + strcpy(result, s.c_str() ); + return result; + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return NULL; + } + + catch (...) + { + return NULL; + } +} + +// Return postgis geometry type index +int GEOSGeometryTypeId(Geometry *g1) +{ + try + { + GeometryTypeId id = g1->getGeometryTypeId(); + switch (id) + { + case GEOS_POINT: + return POINTTYPE; + case GEOS_LINESTRING: + return LINETYPE; + case GEOS_POLYGON: + return POLYGONTYPE; + case GEOS_MULTIPOINT: + return MULTIPOINTTYPE; + case GEOS_MULTILINESTRING: + return MULTILINETYPE; + case GEOS_MULTIPOLYGON: + return MULTIPOLYGONTYPE; + case GEOS_GEOMETRYCOLLECTION: + return COLLECTIONTYPE; + default: + return 0; + } + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return -1; + } + + catch (...) + { + return -1; + } +} + + + + +//------------------------------------------------------------------- +// GEOS functions that return geometries +//------------------------------------------------------------------- + +Geometry *GEOSIntersection(Geometry *g1,Geometry *g2) +{ + try + { + Geometry *g3 = g1->intersection(g2); + return g3; + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return NULL; + } + + catch (...) + { + return NULL; + } +} + +Geometry *GEOSBuffer(Geometry *g1,double width) +{ + try + { + Geometry *g3 = g1->buffer(width); + return g3; + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return NULL; + } + + catch (...) + { + return NULL; + } +} + +Geometry *GEOSConvexHull(Geometry *g1) +{ + try + { + Geometry *g3 = g1->convexHull(); + return g3; + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return NULL; + } + + catch (...) + { + return NULL; + } +} + +Geometry *GEOSDifference(Geometry *g1,Geometry *g2) +{ + try + { + Geometry *g3 = g1->difference(g2); + return g3; + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return NULL; + } + + catch (...) + { + return NULL; + } +} + +Geometry *GEOSBoundary(Geometry *g1) +{ + try + { + Geometry *g3 = g1->getBoundary(); + return g3; + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return NULL; + } + + catch (...) + { + return NULL; + } +} + +Geometry *GEOSSymDifference(Geometry *g1,Geometry *g2) +{ + try + { + Geometry *g3 = g1->symDifference(g2); + return g3; + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return NULL; + } + + catch (...) + { + return NULL; + } +} + +Geometry *GEOSUnion(Geometry *g1,Geometry *g2) +{ + try + { + Geometry *g3 = g1->Union(g2); + return g3; + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return NULL; + } + catch (...) + { + return NULL; + } +} + + +Geometry *GEOSpointonSurface(Geometry *g1) +{ + try + { + Geometry *g3 = g1->getInteriorPoint(); + return g3; + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return NULL; + } + + catch (...) + { + return NULL; + } +} + + + + + +//------------------------------------------------------------------- +// memory management functions +//------------------------------------------------------------------ + + +//BUG:: this leaks memory, but delete kills the PrecisionModel for ALL the geometries +void GEOSdeleteGeometry(Geometry *a) +{ + try{ + delete a; + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + //return NULL; + } + + catch(...) + { + // do nothing! + } +} + +void GEOSdeleteChar(char *a) +{ + try{ + free(a); + } + catch (GEOSException *ge) // ??? + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + //return NULL; + } + + catch(...) + { + // do nothing! + } +} + + +//------------------------------------------------------------------- +//GEOS => POSTGIS conversions +//------------------------------------------------------------------- + + +// free the result when done! +// g1 must be a point +POINT3D *GEOSGetCoordinate(Geometry *g1) +{ + try{ + POINT3D *result = (POINT3D*) malloc (sizeof(POINT3D)); + const Coordinate *c =g1->getCoordinate(); + + result->x = c->x; + result->y = c->y; + result->z = c->z; + return result; + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return NULL; + } + + catch(...) + { + return NULL; + } + +} + + +//must free the result when done +// result is an array length g1->getNumCoordinates() +POINT3D *GEOSGetCoordinates(Geometry *g1) +{ + if ( g1->getGeometryTypeId() == GEOS_POLYGON ) + { + return GEOSGetCoordinates_Polygon((Polygon *)g1); + } + + try { + int numPoints = g1->getNumPoints(); + POINT3D *result = (POINT3D*) malloc (sizeof(POINT3D) * numPoints ); + int t; + CoordinateSequence *cl = g1->getCoordinates(); + Coordinate c; + + for (t=0;tgetAt(t); + + result[t].x = c.x; + result[t].y = c.y; + result[t].z = c.z; + } + + delete cl; + return result; + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return NULL; + } + + catch(...) + { + return NULL; + } + +} + +// A somewhat optimized version for polygon types. +POINT3D *GEOSGetCoordinates_Polygon(Polygon *g1) +{ + try { + int t, r, outidx=0; + const CoordinateSequence *cl; + Coordinate c; + const LineString *lr; + int npts, nrings; + POINT3D *result; + + npts = g1->getNumPoints(); + result = (POINT3D*) malloc (sizeof(POINT3D) * npts); + + // Exterior ring + lr = g1->getExteriorRing(); + cl = lr->getCoordinatesRO(); + npts = lr->getNumPoints(); + for (t=0; tgetAt(t); + + result[outidx].x = c.x; + result[outidx].y = c.y; + result[outidx].z = c.z; + outidx++; + } + + // Interior rings + nrings = g1->getNumInteriorRing(); + for (r=0; rgetInteriorRingN(r); + cl = lr->getCoordinatesRO(); + npts = lr->getNumPoints(); + for (t=0; tgetAt(t); + result[outidx].x = c.x; + result[outidx].y = c.y; + result[outidx].z = c.z; + outidx++; + } + } + + return result; + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return NULL; + } + + catch(...) + { + return NULL; + } + +} + + + + +int GEOSGetNumCoordinate(Geometry *g1) +{ + try{ + return g1->getNumPoints(); + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return 0; + } + + catch(...) + { + return 0; + } +} + +int GEOSGetNumInteriorRings(Geometry *g1) +{ + try{ + Polygon *p = (Polygon *) g1; + return p->getNumInteriorRing(); + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return 0; + } + + catch(...) + { + return 0; + } +} + + +//only call on GCs (or multi*) +int GEOSGetNumGeometries(Geometry *g1) +{ + try{ + GeometryCollection *gc = (GeometryCollection *) g1; + return gc->getNumGeometries(); + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return 0; + } + + catch(...) + { + return 0; + } +} + + +//call only on GEOMETRYCOLLECTION or MULTI* +const Geometry *GEOSGetGeometryN(Geometry *g1, int n) +{ + try{ + const GeometryCollection *gc = (GeometryCollection *) g1; + return gc->getGeometryN(n); + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return NULL; + } + + catch(...) + { + return NULL; + } +} + + +//call only on polygon +const Geometry *GEOSGetExteriorRing(Geometry *g1) +{ + try{ + Polygon *p = (Polygon *) g1; + return p->getExteriorRing(); + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return 0; + } + + catch(...) + { + return 0; + } +} + +//call only on polygon +const Geometry *GEOSGetInteriorRingN(Geometry *g1,int n) +{ + try{ + Polygon *p = (Polygon *) g1; + return p->getInteriorRingN(n); + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return NULL; + } + + catch(...) + { + return NULL; + } +} + +Geometry *GEOSGetCentroid(Geometry *g) +{ + try{ + return g->getCentroid(); + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return NULL; + } + + catch(...) + { + return NULL; + } +} + + +int GEOSGetSRID(Geometry *g1) +{ + try{ + return g1->getSRID(); + } + catch (GEOSException *ge) + { + NOTICE_MESSAGE((char *)ge->toString().c_str()); + delete ge; + return 0; + } + + catch(...) + { + return 0; + } +} + +char * +GEOSversion() +{ +#if GEOS_LAST_INTERFACE < 2 + /* + * GEOS upgrade needs postgis re-build, so this static + * assignment is not going to be a problem + */ + char *res = strdup("1.0.0"); +#else + string version = geosversion(); + char *res = strdup(version.c_str()); +#endif + return res; +} + +char * +GEOSjtsport() +{ +#if GEOS_LAST_INTERFACE < 2 + /* + * GEOS upgrade needs postgis re-build, so this static + * assignment is not going to be a problem + */ + char *res = strdup("1.3"); +#else + string version = jtsport(); + char *res = strdup(version.c_str()); +#endif + return res; +} + + -- 2.50.1