From c78d0287b51a7eb8cde36d9ded22f381a6be8136 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Fri, 6 Jun 2008 08:48:10 +0000 Subject: [PATCH] Remove JTS support from liblwpostgis; native GCJ-compiled JTS code is reported not to be reliable enough within a production environment, so well stick with GEOS. git-svn-id: http://svn.osgeo.org/postgis/trunk@2808 b70326c6-7e19-0410-871a-916f4a2858ee --- lwgeom/lwgeom_jts.c | 3211 --------------------------------- lwgeom/lwgeom_jts_wrapper.cpp | 1211 ------------- lwgeom/lwgeom_nojts.c | 326 ---- 3 files changed, 4748 deletions(-) delete mode 100644 lwgeom/lwgeom_jts.c delete mode 100644 lwgeom/lwgeom_jts_wrapper.cpp delete mode 100644 lwgeom/lwgeom_nojts.c diff --git a/lwgeom/lwgeom_jts.c b/lwgeom/lwgeom_jts.c deleted file mode 100644 index ea2ec18a5..000000000 --- a/lwgeom/lwgeom_jts.c +++ /dev/null @@ -1,3211 +0,0 @@ - -#include "postgres.h" -#include "utils/array.h" -#include "utils/builtins.h" -#include "fmgr.h" - -#include "lwgeom_pg.h" -#include "liblwgeom.h" -#include "profile.h" -#include "wktparse.h" - -Datum relate_full(PG_FUNCTION_ARGS); -Datum relate_pattern(PG_FUNCTION_ARGS); -Datum disjoint(PG_FUNCTION_ARGS); -Datum touches(PG_FUNCTION_ARGS); -Datum intersects_reprecated(PG_FUNCTION_ARGS); -Datum intersects(PG_FUNCTION_ARGS); -Datum crosses(PG_FUNCTION_ARGS); -Datum within(PG_FUNCTION_ARGS); -Datum contains(PG_FUNCTION_ARGS); -Datum covers(PG_FUNCTION_ARGS); -Datum overlaps(PG_FUNCTION_ARGS); -Datum isvalid(PG_FUNCTION_ARGS); -Datum buffer(PG_FUNCTION_ARGS); -Datum intersection(PG_FUNCTION_ARGS); -Datum convexhull(PG_FUNCTION_ARGS); -Datum difference(PG_FUNCTION_ARGS); -Datum boundary(PG_FUNCTION_ARGS); -Datum symdifference(PG_FUNCTION_ARGS); -Datum geomunion(PG_FUNCTION_ARGS); -Datum unite_garray(PG_FUNCTION_ARGS); -Datum issimple(PG_FUNCTION_ARGS); -Datum isring(PG_FUNCTION_ARGS); -Datum geomequals(PG_FUNCTION_ARGS); -Datum pointonsurface(PG_FUNCTION_ARGS); -Datum JTSnoop(PG_FUNCTION_ARGS); -Datum postgis_geos_version(PG_FUNCTION_ARGS); -Datum centroid(PG_FUNCTION_ARGS); -Datum polygonize_garray(PG_FUNCTION_ARGS); -Datum polygonize_garray(PG_FUNCTION_ARGS); -Datum LWGEOM_buildarea(PG_FUNCTION_ARGS); -Datum linemerge(PG_FUNCTION_ARGS); - -/* - * Define this to have have many notices printed - * during postgis->geos and geos->postgis conversions - */ -//#define PGIS_DEBUG_CONVERTER 1 -#ifdef PGIS_DEBUG_CONVERTER -#define PGIS_DEBUG_POSTGIS2JTS 1 -#define PGIS_DEBUG_JTS2POSTGIS 1 -#endif // PGIS_DEBUG_CONVERTER -//#define PGIS_DEBUG 1 -//#define PGIS_DEBUG_POSTGIS2JTS - -/* - * If you're having problems with JTS<->POSTGIS conversions - * you can define these to use WKT - */ -#define WKT_J2P 0 -#define WKT_P2J 0 - -typedef void (*noticefunc)(const char *fmt, ...); -typedef struct JTSGeometry JTSGeometry; -typedef struct JTSPrepGeometry JTSPrepGeometry; - -extern const char * createJTSPoint(POINT3D *pt); -extern void initJTS(noticefunc); -extern void finishJTS(void); -extern char *JTSrelate(JTSGeometry *g1, JTSGeometry*g2); -extern char JTSrelatePattern(JTSGeometry *g1, JTSGeometry*g2,char *pat); -extern char JTSrelateDisjoint(JTSGeometry *g1, JTSGeometry*g2); -extern char JTSrelateTouches(JTSGeometry *g1, JTSGeometry*g2); -extern char JTSrelateIntersects(JTSGeometry *g1, JTSGeometry*g2); -extern char JTSrelateCrosses(JTSGeometry *g1, JTSGeometry*g2); -extern char JTSrelateWithin(JTSGeometry *g1, JTSGeometry*g2); -extern char JTSrelateContains(JTSGeometry *g1, JTSGeometry*g2); -extern char JTSrelateOverlaps(JTSGeometry *g1, JTSGeometry*g2); -extern char *JTSasText(JTSGeometry *g1); -extern char JTSisEmpty(JTSGeometry *g1); -extern char *JTSGeometryType(JTSGeometry *g1); -extern int JTSGeometryTypeId(JTSGeometry *g1); -extern char *JTSversion(); -extern char *JTSjtsport(); -extern char JTSisvalid(JTSGeometry *g1); -extern JTSGeometry *JTSIntersection(JTSGeometry *g1, JTSGeometry *g2); -extern JTSGeometry *JTSBuffer(JTSGeometry *g1,double width, int quadsegs); -extern JTSGeometry *JTSConvexHull(JTSGeometry *g1); -extern JTSGeometry *JTSDifference(JTSGeometry *g1,JTSGeometry *g2); -extern JTSGeometry *JTSBoundary(JTSGeometry *g1); -extern JTSGeometry *JTSSymDifference(JTSGeometry *g1,JTSGeometry *g2); -extern JTSGeometry *JTSUnion(JTSGeometry *g1,JTSGeometry *g2); -extern char JTSequals(JTSGeometry *g1, JTSGeometry*g2); -extern char JTSisSimple(JTSGeometry *g1); -extern char JTSisRing(JTSGeometry *g1); -extern JTSGeometry *JTSpointonSurface(JTSGeometry *g1); -extern JTSGeometry *JTSGetCentroid(JTSGeometry *g, int *failure); -extern bool JTSHasZ(JTSGeometry *g1); - -extern void JTSSetSRID(JTSGeometry *g, int SRID); -extern void JTSdeleteChar(char *a); - -extern POINT3D *JTSGetCoordinate(JTSGeometry *g1); -extern POINT3D *JTSGetCoordinates(JTSGeometry *g1); -extern int JTSGetNumCoordinate(JTSGeometry *g1); -extern JTSGeometry *JTSGetGeometryN(JTSGeometry *g1, int n); -extern JTSGeometry *JTSGetExteriorRing(JTSGeometry *g1); -extern JTSGeometry *JTSGetInteriorRingN(JTSGeometry *g1,int n); -extern JTSGeometry *JTSPolygonize(JTSGeometry **geoms, unsigned int ngeoms); -extern JTSGeometry *JTSLineMerge(JTSGeometry *geoms); -extern int JTSGetNumInteriorRings(JTSGeometry *g1); -extern int JTSGetSRID(JTSGeometry *g1); -extern int JTSGetNumGeometries(JTSGeometry *g1); - -extern JTSGeometry *PostGIS2JTS_point(const LWPOINT *point); -extern JTSGeometry *PostGIS2JTS_linestring(const LWLINE *line); -extern JTSGeometry *PostGIS2JTS_polygon(const LWPOLY *polygon); -extern JTSGeometry *PostGIS2JTS_multipolygon(LWPOLY **geoms, uint32 ngeoms, int SRID, int is3d); -extern JTSGeometry *PostGIS2JTS_multilinestring(LWLINE **geoms, uint32 ngeoms, int SRID, int is3d); -extern JTSGeometry *PostGIS2JTS_multipoint(LWPOINT **geoms, uint32 ngeoms, int SRID, int is3d); -extern JTSGeometry *PostGIS2JTS_collection(int type, JTSGeometry **geoms, int ngeoms, int SRID, bool is3d); -extern JTSGeometry *JTSGeometryFromWKT(const char *wkt); - -PG_LWGEOM *JTS2POSTGIS(JTSGeometry *geom, char want3d); -JTSGeometry * POSTGIS2JTS(PG_LWGEOM *g); -JTSGeometry * LWGEOM2JTS(LWGEOM *g); -void errorIfJTSGeometryCollection(PG_LWGEOM *g1, PG_LWGEOM *g2); -LWPOINT *lwpoint_from_geometry(JTSGeometry *g, char want3d); -LWLINE *lwline_from_geometry(JTSGeometry *g, char want3d); -LWPOLY *lwpoly_from_geometry(JTSGeometry *g, char want3d); -LWCOLLECTION *lwcollection_from_geometry(JTSGeometry *geom, char want3d); -LWGEOM *JTS2LWGEOM(JTSGeometry *g, char want3d); -void JTSPrintPreparedGeometry(JTSGeometry *pg); -JTSPrepGeometry *JTSGetRHSCache(); -JTSPrepGeometry *JTSGetLHSCache(); -void JTSPutRHSCache(JTSPrepGeometry *rhs); -void JTSPutLHSCache(JTSPrepGeometry *lhs); - -typedef struct -{ - uchar *serializedGeomA; - uchar *serializedGeomB; -} PREPARED_GEOMETRY_CACHE; - -char JTSpreparedIntersects(JTSPrepGeometry *pg, JTSGeometry *g); -JTSPrepGeometry *JTSPrepareGeometry(JTSGeometry *g); - -/* - * Using BUFFER(0) version of unite_garray takes - * processing to a segfault (after spending a lot of time!) - */ -#undef UNITE_USING_BUFFER - -#ifndef UNITE_USING_BUFFER -/* - * This is the final function for geomunion - * aggregate. Will have as input an array of Geometries. - * Will iteratively call JTSUnion on the JTS-converted - * versions of them and return PGIS-converted version back. - * Changing combination order *might* speed up performance. - * - */ -PG_FUNCTION_INFO_V1(unite_garray); -Datum unite_garray(PG_FUNCTION_ARGS) -{ - Datum datum; - ArrayType *array; - int is3d = 0; - int nelems, i; - PG_LWGEOM *result, *pgis_geom; - JTSGeometry *g1, *g2, *geos_result=NULL; - int SRID=-1; - size_t offset; -#ifdef PGIS_DEBUG - static int call=1; -#endif - -#ifdef PGIS_DEBUG - call++; -#endif - - lwnotice("JTS incremental union"); - - datum = PG_GETARG_DATUM(0); - - /* Null array, null geometry (should be empty?) */ - if ( (Pointer *)datum == NULL ) PG_RETURN_NULL(); - - array = DatumGetArrayTypeP(datum); - - nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array)); - -#ifdef PGIS_DEBUG - elog(NOTICE, "unite_garray: number of elements: %d", nelems); -#endif - - if ( nelems == 0 ) PG_RETURN_NULL(); - - /* One-element union is the element itself */ - if ( nelems == 1 ) PG_RETURN_POINTER((PG_LWGEOM *)(ARR_DATA_PTR(array))); - - /* Ok, we really need geos now ;) */ - initJTS(lwnotice); - - offset = 0; - for (i=0; itype) > 2 ) is3d = 1; - - // Check SRID homogeneity and initialize geos result - if ( ! i ) - { - geos_result = POSTGIS2JTS(geom); - SRID = pglwgeom_getSRID(geom); -#ifdef PGIS_DEBUG - elog(NOTICE, "first geom is a %s", lwgeom_typename(TYPE_GETTYPE(geom->type))); -#endif - continue; - } - else - { - errorIfSRIDMismatch(SRID, pglwgeom_getSRID(geom)); - } - - g1 = POSTGIS2JTS(pgis_geom); - if ( g1 == NULL ) - { - finishJTS(); - lwerror("unite_garray: error converting geometry %d to JTS", i); - } - -#ifdef PGIS_DEBUG - lwnotice( "unite_garray(%d): adding geom %d to union (%s)", - call, i, lwgeom_typename(TYPE_GETTYPE(geom->type))); -#endif - - g2 = JTSUnion(g1,geos_result); - if ( g2 == NULL ) - { -//#define PGIS_SQL_FAILURES 1 - -#ifdef PGIS_SQL_FAILURES - LWGEOM *failing1, *failing2; - char *hexwkb1, *hexwkb2; - - failing1 = JTS2LWGEOM(g1, 0); - failing2 = JTS2LWGEOM(geos_result, 0); - - failing1->SRID=-1; - failing2->SRID=-1; - - hexwkb1 = lwgeom_to_hexwkb(failing1, getMachineEndian()); - hexwkb2 = lwgeom_to_hexwkb(failing2, getMachineEndian()); - - lwnotice("\nINSERT INTO jts_failures(g1,g2,op) VALUES ('%s', '%s', 'union');", - hexwkb1, hexwkb2); - - lwgeom_release(failing1); - lwgeom_release(failing2); - - // let it leak (getting memory errors otherwise) - //free(hexwkb1); - //free(hexwkb2); -#endif - finishJTS(); - lwerror("JTS union() threw an error!"); - PG_RETURN_NULL(); - } - - //finishJTS(); - geos_result = g2; - g2 = NULL; // FOR GC - } - - lwnotice("unite_garray finished all elements (%d)", nelems); - - JTSSetSRID(geos_result, SRID); - result = JTS2POSTGIS(geos_result, is3d); - if ( result == NULL ) { - finishJTS(); - lwerror("JTS2POSTGIS returned an error"); - PG_RETURN_NULL(); - } - - finishJTS(); - PG_RETURN_POINTER(result); - -} - -#else // def UNITE_USING_BUFFER - -/* - * This is the final function for GeomUnion - * aggregate. Will have as input an array of Geometries. - * Builds a GEOMETRYCOLLECTION from input and call - * JTSBuffer(collection, 0) on the JTS-converted - * versions of it. Returns PGIS-converted version back. - */ -PG_FUNCTION_INFO_V1(unite_garray); -Datum unite_garray(PG_FUNCTION_ARGS) -{ - Datum datum; - ArrayType *array; - int is3d = 0; - int nelems, i; - PG_LWGEOM *result, *pgis_geom; - LWGEOM **lwgeoms, *collection; - JTSGeometry *g1, *geos_result=NULL; - int SRID=-1; - size_t offset; -#ifdef PGIS_DEBUG - static int call=1; -#endif - -#ifdef PGIS_DEBUG - call++; -#endif - - lwnotice("JTS buffer union"); - - datum = PG_GETARG_DATUM(0); - - /* Null array, null geometry (should be empty?) */ - if ( (Pointer *)datum == NULL ) PG_RETURN_NULL(); - - array = DatumGetArrayTypeP(datum); - - nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array)); - -#ifdef PGIS_DEBUG - elog(NOTICE, "unite_garray: number of elements: %d", nelems); -#endif - - if ( nelems == 0 ) PG_RETURN_NULL(); - - /* One-element union is the element itself */ - if ( nelems == 1 ) PG_RETURN_POINTER((PG_LWGEOM *)(ARR_DATA_PTR(array))); - - lwgeoms = lwalloc(sizeof(LWGEOM *)*nelems); - - offset = 0; - for (i=0; itype) > 2 ) is3d = 1; - - // Check SRID homogeneity - if ( ! i ) SRID = pglwgeom_getSRID(geom); - else errorIfSRIDMismatch(SRID, pglwgeom_getSRID(geom)); - - lwgeoms[i] = lwgeom_deserialize(SERIALIZED_FORM(pgis_geom)); - - } - - /* Let's build a GEOMETRYCOLLECTION */ - collection = (LWGEOM *)lwcollection_construct(COLLECTIONTYPE, -1, - NULL, nelems, lwgeoms); - - /* Ok, we really need JTS now */ - initJTS(lwnotice); - - g1 = LWGEOM2JTS(collection); - - /* we don't need these anymore */ - lwgeom_release(collection); - - geos_result = JTSBuffer(g1, 0, 0); - g1=NULL; - if ( geos_result == NULL ) - { - finishJTS(); - lwerror("GEOS buffer() threw an error!"); - } - JTSSetSRID(geos_result, SRID); - - result = JTS2POSTGIS(geos_result, is3d); - geos_result=NULL; - - finishJTS(); - - if ( result == NULL ) - lwerror("JTS2POSTGIS returned an error"); - - //compressType(result); - - PG_RETURN_POINTER(result); - -} - -#endif // def UNITE_USING_BUFFER - - -//select geomunion('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))','POLYGON((5 5, 15 5, 15 7, 5 7, 5 5))'); -PG_FUNCTION_INFO_V1(geomunion); -Datum geomunion(PG_FUNCTION_ARGS) -{ - PG_LWGEOM *geom1; - PG_LWGEOM *geom2; - int is3d; - int SRID; - JTSGeometry *g1,*g2,*g3; - PG_LWGEOM *result; - -#ifdef PROFILE - profstart(PROF_QRUN); -#endif - - geom1 = (PG_LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - geom2 = (PG_LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); - - is3d = ( TYPE_NDIMS(geom1->type) > 2 ) || - ( TYPE_NDIMS(geom2->type) > 2 ); - - SRID = pglwgeom_getSRID(geom1); - errorIfSRIDMismatch(SRID, pglwgeom_getSRID(geom2)); - - initJTS(lwnotice); -//elog(NOTICE,"in geomunion"); - -#ifdef PROFILE - profstart(PROF_P2G1); -#endif - g1 = POSTGIS2JTS(geom1); -#ifdef PROFILE - profstop(PROF_P2G1); -#endif -#ifdef PROFILE - profstart(PROF_P2G2); -#endif - g2 = POSTGIS2JTS(geom2); -#ifdef PROFILE - profstop(PROF_P2G2); -#endif - -//elog(NOTICE,"g1=%s",JTSasText(g1)); -//elog(NOTICE,"g2=%s",JTSasText(g2)); -#ifdef PROFILE - profstart(PROF_GRUN); -#endif - g3 = JTSUnion(g1,g2); -#ifdef PROFILE - profstop(PROF_GRUN); -#endif - -//elog(NOTICE,"g3=%s",JTSasText(g3)); - - if (g3 == NULL) - { - finishJTS(); - lwerror("JTS union() threw an error!"); - PG_RETURN_NULL(); //never get here - } - - - JTSSetSRID(g3, SRID); - -//elog(NOTICE,"result: %s", JTSasText(g3) ) ; - -#ifdef PROFILE - profstart(PROF_G2P); -#endif - result = JTS2POSTGIS(g3, is3d); -#ifdef PROFILE - profstop(PROF_G2P); -#endif - - if (result == NULL) - { - elog(ERROR,"JTS union() threw an error (result postgis geometry formation)!"); - PG_RETURN_NULL(); //never get here - } - -#ifdef PROFILE - profstop(PROF_QRUN); - profreport("jts",geom1, geom2, result); -#endif - - PG_FREE_IF_COPY(geom1, 0); - PG_FREE_IF_COPY(geom2, 1); - finishJTS(); - - PG_RETURN_POINTER(result); -} - - -// select symdifference('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))','POLYGON((5 5, 15 5, 15 7, 5 7, 5 5))'); -PG_FUNCTION_INFO_V1(symdifference); -Datum symdifference(PG_FUNCTION_ARGS) -{ - PG_LWGEOM *geom1; - PG_LWGEOM *geom2; - JTSGeometry *g1,*g2,*g3; - PG_LWGEOM *result; - int is3d; - int SRID; - -#ifdef PROFILE - profstart(PROF_QRUN); -#endif - - geom1 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - geom2 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); - - is3d = ( TYPE_NDIMS(geom1->type) > 2 ) || - ( TYPE_NDIMS(geom2->type) > 2 ); - - SRID = pglwgeom_getSRID(geom1); - errorIfSRIDMismatch(SRID, pglwgeom_getSRID(geom2)); - - initJTS(lwnotice); - -#ifdef PROFILE - profstart(PROF_P2G1); -#endif - g1 = POSTGIS2JTS(geom1); -#ifdef PROFILE - profstop(PROF_P2G1); -#endif -#ifdef PROFILE - profstart(PROF_P2G2); -#endif - g2 = POSTGIS2JTS(geom2); -#ifdef PROFILE - profstop(PROF_P2G2); -#endif - -#ifdef PROFILE - profstart(PROF_GRUN); -#endif - g3 = JTSSymDifference(g1,g2); -#ifdef PROFILE - profstop(PROF_GRUN); -#endif - - if (g3 == NULL) - { - finishJTS(); - lwerror("JTS symdifference() threw an error!"); - PG_RETURN_NULL(); //never get here - } - -// elog(NOTICE,"result: %s", JTSasText(g3) ) ; - - JTSSetSRID(g3, SRID); - -#ifdef PROFILE - profstart(PROF_G2P); -#endif - result = JTS2POSTGIS(g3, is3d); -#ifdef PROFILE - profstop(PROF_G2P); -#endif - - if (result == NULL) - { - finishJTS(); - lwerror("JTS symdifference() threw an error (result postgis geometry formation)!"); - PG_RETURN_NULL(); //never get here - } - -#ifdef PROFILE - profstop(PROF_QRUN); - profreport("jts",geom1, geom2, result); -#endif - - PG_FREE_IF_COPY(geom1, 0); - PG_FREE_IF_COPY(geom2, 1); - finishJTS(); - - PG_RETURN_POINTER(result); -} - - -PG_FUNCTION_INFO_V1(boundary); -Datum boundary(PG_FUNCTION_ARGS) -{ - PG_LWGEOM *geom1; - JTSGeometry *g1,*g3; - PG_LWGEOM *result; - int SRID; - -#ifdef PROFILE - profstart(PROF_QRUN); -#endif - - geom1 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - - SRID = pglwgeom_getSRID(geom1); - - initJTS(lwnotice); - -#ifdef PROFILE - profstart(PROF_P2G1); -#endif - g1 = POSTGIS2JTS(geom1 ); -#ifdef PROFILE - profstop(PROF_P2G1); -#endif - -#ifdef PROFILE - profstart(PROF_GRUN); -#endif - g3 = JTSBoundary(g1); -#ifdef PROFILE - profstop(PROF_GRUN); -#endif - - if (g3 == NULL) - { - finishJTS(); - lwerror("JTS boundary() threw an error!"); - PG_RETURN_NULL(); //never get here - } - -// elog(NOTICE,"result: %s", JTSasText(g3) ) ; - - JTSSetSRID(g3, SRID); - -#ifdef PROFILE - profstart(PROF_G2P); -#endif - result = JTS2POSTGIS(g3, TYPE_NDIMS(geom1->type) > 2); -#ifdef PROFILE - profstart(PROF_P2G1); -#endif - - if (result == NULL) - { - finishJTS(); - lwerror("JTS boundary() threw an error (result postgis geometry formation)!"); - PG_RETURN_NULL(); //never get here - } - - - finishJTS(); - -#ifdef PROFILE - profstop(PROF_QRUN); - profreport("jts",geom1, NULL, result); -#endif - - PG_FREE_IF_COPY(geom1, 0); - - PG_RETURN_POINTER(result); -} - -PG_FUNCTION_INFO_V1(convexhull); -Datum convexhull(PG_FUNCTION_ARGS) -{ - PG_LWGEOM *geom1; - JTSGeometry *g1, *g3; - PG_LWGEOM *result; - LWGEOM *lwout; - int SRID; - BOX2DFLOAT4 bbox; - -#ifdef PROFILE - profstart(PROF_QRUN); -#endif - - geom1 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - SRID = pglwgeom_getSRID(geom1); - - initJTS(lwnotice); - -#ifdef PROFILE - profstart(PROF_P2G1); -#endif - g1 = POSTGIS2JTS(geom1); -#ifdef PROFILE - profstop(PROF_P2G1); -#endif - if (g1 == NULL) - { - finishJTS(); - lwerror("JTS convexhull() threw an error!"); - PG_RETURN_NULL(); //never get here - } - -#ifdef PROFILE - profstart(PROF_GRUN); -#endif - g3 = JTSConvexHull(g1); -#ifdef PROFILE - profstop(PROF_GRUN); -#endif - - if (g3 == NULL) - { - finishJTS(); - lwerror("JTS convexhull() threw an error!"); - PG_RETURN_NULL(); //never get here - } - - - //elog(NOTICE,"result: %s", JTSasText(g3) ) ; - JTSSetSRID(g3, SRID); - -#ifdef PROFILE - profstart(PROF_G2P); -#endif - lwout = JTS2LWGEOM(g3, TYPE_NDIMS(geom1->type) > 2); -#ifdef PROFILE - profstop(PROF_G2P); -#endif - if (lwout == NULL) - { - finishJTS(); - lwerror("convexhull() failed to convert JTS geometry to LWGEOM"); - PG_RETURN_NULL(); //never get here - } - - /* Copy input bbox if any */ - if ( getbox2d_p(SERIALIZED_FORM(geom1), &bbox) ) - { - lwout->bbox = box2d_clone(&bbox); - } - - result = pglwgeom_serialize(lwout); - if (result == NULL) - { - finishJTS(); - lwerror("JTS convexhull() threw an error (result postgis geometry formation)!"); - PG_RETURN_NULL(); //never get here - } - - lwgeom_release(lwout); - finishJTS(); - -#ifdef PROFILE - profstop(PROF_QRUN); - profreport("jts",geom1, NULL, result); -#endif - - PG_FREE_IF_COPY(geom1, 0); - - PG_RETURN_POINTER(result); - -} - -PG_FUNCTION_INFO_V1(buffer); -Datum buffer(PG_FUNCTION_ARGS) -{ - PG_LWGEOM *geom1; - double size; - JTSGeometry *g1,*g3; - PG_LWGEOM *result; - int quadsegs = 8; // the default - -#ifdef PROFILE - profstart(PROF_QRUN); -#endif - - geom1 = (PG_LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - size = PG_GETARG_FLOAT8(1); - if ( PG_NARGS() > 2 ) quadsegs = PG_GETARG_INT32(2); - - initJTS(lwnotice); - -#ifdef PROFILE - profstart(PROF_P2G1); -#endif - g1 = POSTGIS2JTS(geom1); -#ifdef PROFILE - profstop(PROF_P2G1); -#endif - -#ifdef PROFILE - profstart(PROF_GRUN); -#endif - g3 = JTSBuffer(g1,size,quadsegs); - g1=NULL; // for GC -#ifdef PROFILE - profstop(PROF_GRUN); -#endif - - if (g3 == NULL) - { - finishJTS(); - lwerror("JTS buffer() threw an error!"); - PG_RETURN_NULL(); //never get here - } - - -// elog(NOTICE,"result: %s", JTSasText(g3) ) ; - - JTSSetSRID(g3, pglwgeom_getSRID(geom1)); - -#ifdef PROFILE - profstart(PROF_G2P); -#endif - result = JTS2POSTGIS(g3, TYPE_NDIMS(geom1->type) > 2); -#ifdef PROFILE - profstop(PROF_G2P); -#endif - if (result == NULL) - { - finishJTS(); - lwerror("JTS buffer() threw an error (result postgis geometry formation)!"); - PG_RETURN_NULL(); //never get here - } - - g3=NULL; // for GC - finishJTS(); - - -#ifdef PROFILE - profstop(PROF_QRUN); - profreport("jts",geom1, NULL, result); -#endif - - PG_FREE_IF_COPY(geom1, 0); - - PG_RETURN_POINTER(result); -} - -PG_FUNCTION_INFO_V1(intersection); -Datum intersection(PG_FUNCTION_ARGS) -{ - PG_LWGEOM *geom1; - PG_LWGEOM *geom2; - JTSGeometry *g1,*g2,*g3; - PG_LWGEOM *result; - int is3d; - int SRID; - -#ifdef PROFILE - profstart(PROF_QRUN); -#endif - - geom1 = (PG_LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - geom2 = (PG_LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); - - is3d = ( TYPE_NDIMS(geom1->type) > 2 ) || - ( TYPE_NDIMS(geom2->type) > 2 ); - - SRID = pglwgeom_getSRID(geom1); - errorIfSRIDMismatch(SRID, pglwgeom_getSRID(geom2)); - - initJTS(lwnotice); - -//elog(NOTICE,"intersection() START"); - -#ifdef PROFILE - profstart(PROF_P2G1); -#endif - g1 = POSTGIS2JTS(geom1); -#ifdef PROFILE - profstop(PROF_P2G1); -#endif - -#ifdef PROFILE - profstart(PROF_P2G2); -#endif - g2 = POSTGIS2JTS(geom2); -#ifdef PROFILE - profstop(PROF_P2G2); -#endif - -//elog(NOTICE," constructed geometrys - calling geos"); - -//elog(NOTICE,"g1 = %s",JTSasText(g1)); -//elog(NOTICE,"g2 = %s",JTSasText(g2)); - - -//if (g1==NULL) -// elog(NOTICE,"g1 is null"); -//if (g2==NULL) -// elog(NOTICE,"g2 is null"); -//elog(NOTICE,"g2 is valid = %i",JTSisvalid(g2)); -//elog(NOTICE,"g1 is valid = %i",JTSisvalid(g1)); - - -#ifdef PROFILE - profstart(PROF_GRUN); -#endif - g3 = JTSIntersection(g1,g2); -#ifdef PROFILE - profstop(PROF_GRUN); -#endif - -//elog(NOTICE," intersection finished"); - - if (g3 == NULL) - { - finishJTS(); - lwerror("JTS Intersection() threw an error!"); - PG_RETURN_NULL(); //never get here - } - - - //elog(NOTICE,"result: %s", JTSasText(g3) ) ; - JTSSetSRID(g3, SRID); - -#ifdef PROFILE - profstart(PROF_G2P); -#endif - result = JTS2POSTGIS(g3, is3d); -#ifdef PROFILE - profstop(PROF_G2P); -#endif - - if (result == NULL) - { - finishJTS(); - lwerror("JTS Intersection() threw an error (result postgis geometry formation)!"); - PG_RETURN_NULL(); //never get here - } - - - - finishJTS(); - - //compressType(result); // convert multi* to single item if appropriate - -#ifdef PROFILE - profstop(PROF_QRUN); - profreport("jts",geom1, geom2, result); -#endif - - PG_FREE_IF_COPY(geom1, 0); - PG_FREE_IF_COPY(geom2, 1); - - PG_RETURN_POINTER(result); -} - -//select difference('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))','POLYGON((5 5, 15 5, 15 7, 5 7, 5 5))'); -PG_FUNCTION_INFO_V1(difference); -Datum difference(PG_FUNCTION_ARGS) -{ - PG_LWGEOM *geom1; - PG_LWGEOM *geom2; - JTSGeometry *g1,*g2,*g3; - PG_LWGEOM *result; - int is3d; - int SRID; - -#ifdef PROFILE - profstart(PROF_QRUN); -#endif - - geom1 = (PG_LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - geom2 = (PG_LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); - - is3d = ( TYPE_NDIMS(geom1->type) > 2 ) || - ( TYPE_NDIMS(geom2->type) > 2 ); - - SRID = pglwgeom_getSRID(geom1); - errorIfSRIDMismatch(SRID, pglwgeom_getSRID(geom2)); - - initJTS(lwnotice); - -#ifdef PROFILE - profstart(PROF_P2G1); -#endif - g1 = POSTGIS2JTS(geom1); -#ifdef PROFILE - profstop(PROF_P2G1); -#endif -#ifdef PROFILE - profstart(PROF_P2G2); -#endif - g2 = POSTGIS2JTS(geom2); -#ifdef PROFILE - profstop(PROF_P2G2); -#endif - -#ifdef PROFILE - profstart(PROF_GRUN); -#endif - g3 = JTSDifference(g1,g2); -#ifdef PROFILE - profstop(PROF_GRUN); -#endif - - if (g3 == NULL) - { - finishJTS(); - lwerror("JTS difference() threw an error!"); - PG_RETURN_NULL(); //never get here - } - -// elog(NOTICE,"result: %s", JTSasText(g3) ) ; - - JTSSetSRID(g3, SRID); - -#ifdef PROFILE - profstart(PROF_G2P); -#endif - result = JTS2POSTGIS(g3, is3d); -#ifdef PROFILE - profstop(PROF_G2P); -#endif - if (result == NULL) - { - finishJTS(); - lwerror("JTS difference() threw an error (result postgis geometry formation)!"); - PG_RETURN_NULL(); //never get here - } - - finishJTS(); - - -#ifdef PROFILE - profstop(PROF_QRUN); - profreport("jts",geom1, geom2, result); -#endif - - PG_FREE_IF_COPY(geom1, 0); - PG_FREE_IF_COPY(geom2, 1); - - PG_RETURN_POINTER(result); -} - - -//select pointonsurface('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))'); -PG_FUNCTION_INFO_V1(pointonsurface); -Datum pointonsurface(PG_FUNCTION_ARGS) -{ - PG_LWGEOM *geom1; - JTSGeometry *g1,*g3; - PG_LWGEOM *result; - -#ifdef PROFILE - profstart(PROF_QRUN); -#endif - - geom1 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - - initJTS(lwnotice); - -#ifdef PROFILE - profstart(PROF_P2G1); -#endif - g1 = POSTGIS2JTS(geom1); -#ifdef PROFILE - profstop(PROF_P2G1); -#endif - -#ifdef PROFILE - profstart(PROF_GRUN); -#endif - g3 = JTSpointonSurface(g1); -#ifdef PROFILE - profstop(PROF_GRUN); -#endif - - if (g3 == NULL) - { - finishJTS(); - lwerror("JTS pointonsurface() threw an error!"); - PG_RETURN_NULL(); //never get here - } - -// elog(NOTICE,"result: %s", JTSasText(g3) ) ; - - JTSSetSRID(g3, pglwgeom_getSRID(geom1)); -#ifdef PROFILE - profstart(PROF_G2P); -#endif - result = JTS2POSTGIS(g3, (TYPE_NDIMS(geom1->type) > 2)); -#ifdef PROFILE - profstop(PROF_G2P); -#endif - if (result == NULL) - { - finishJTS(); - lwerror("JTS pointonsurface() threw an error (result postgis geometry formation)!"); - PG_RETURN_NULL(); //never get here - } - - finishJTS(); - -#ifdef PROFILE - profstop(PROF_QRUN); - profreport("jts",geom1, NULL, result); -#endif - - PG_FREE_IF_COPY(geom1, 0); - - PG_RETURN_POINTER(result); -} - -PG_FUNCTION_INFO_V1(centroid); -Datum centroid(PG_FUNCTION_ARGS) -{ - PG_LWGEOM *geom, *result; - JTSGeometry *geosgeom, *geosresult; - int failure; - -#ifdef PROFILE - profstart(PROF_QRUN); -#endif - - geom = (PG_LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - - initJTS(lwnotice); - -#ifdef PROFILE - profstart(PROF_P2G1); -#endif - geosgeom = POSTGIS2JTS(geom); -#ifdef PROFILE - profstop(PROF_P2G1); -#endif - -#ifdef PROFILE - profstart(PROF_GRUN); -#endif - geosresult = JTSGetCentroid(geosgeom, &failure); -#ifdef PROFILE - profstop(PROF_GRUN); -#endif - - if ( geosresult == NULL ) - { - finishJTS(); - if ( failure ) { - lwerror("JTS getCentroid() threw an error!"); - } - PG_RETURN_NULL(); - } - - JTSSetSRID(geosresult, pglwgeom_getSRID(geom)); - -#ifdef PROFILE - profstart(PROF_G2P); -#endif - result = JTS2POSTGIS(geosresult, (TYPE_NDIMS(geom->type) > 2)); -#ifdef PROFILE - profstop(PROF_G2P); -#endif - if (result == NULL) - { - finishJTS(); - lwerror("Error in JTS-PGIS conversion"); - PG_RETURN_NULL(); - } - - finishJTS(); - -#ifdef PROFILE - profstop(PROF_QRUN); - profreport("jts",geom, NULL, result); -#endif - - PG_FREE_IF_COPY(geom, 0); - - PG_RETURN_POINTER(result); -} - - - -//---------------------------------------------- - - - -void -errorIfJTSGeometryCollection(PG_LWGEOM *g1, PG_LWGEOM *g2) -{ - int t1 = lwgeom_getType(g1->type); - int t2 = lwgeom_getType(g2->type); - - if ( (t1 == COLLECTIONTYPE) || (t2 == COLLECTIONTYPE) ) - elog(ERROR,"Relate Operation called with a LWGEOMCOLLECTION type. This is unsupported"); -} - -PG_FUNCTION_INFO_V1(isvalid); -Datum isvalid(PG_FUNCTION_ARGS) -{ - PG_LWGEOM *geom1; - LWGEOM *lwgeom; - bool result; - JTSGeometry *g1; - -#ifdef PROFILE - profstart(PROF_QRUN); -#endif - - geom1 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - - initJTS(lwnotice); - -#ifdef PROFILE - profstart(PROF_P2G1); -#endif - lwgeom = lwgeom_deserialize(SERIALIZED_FORM(geom1)); - if ( ! lwgeom ) - { - lwerror("unable to deserialize input"); - } - g1 = LWGEOM2JTS(lwgeom); - if ( ! g1 ) - { - finishJTS(); - lwgeom_release(lwgeom); - PG_RETURN_BOOL(FALSE); - } - lwgeom_release(lwgeom); - //g1 = POSTGIS2JTS(geom1); -#ifdef PROFILE - profstop(PROF_P2G1); -#endif - -#ifdef PROFILE - profstart(PROF_GRUN); -#endif - result = JTSisvalid(g1); -#ifdef PROFILE - profstop(PROF_GRUN); -#endif - - finishJTS(); - - if (result == 2) - { - elog(ERROR,"JTS isvalid() threw an error!"); - PG_RETURN_NULL(); //never get here - } - - -#ifdef PROFILE - profstop(PROF_QRUN); - profreport("jts",geom1, NULL, NULL); -#endif - - PG_FREE_IF_COPY(geom1, 0); - - PG_RETURN_BOOL(result); -} - - -// overlaps(PG_LWGEOM g1,PG_LWGEOM g2) -// returns if JTS::g1->overlaps(g2) returns true -// throws an error (elog(ERROR,...)) if JTS throws an error -PG_FUNCTION_INFO_V1(overlaps); -Datum overlaps(PG_FUNCTION_ARGS) -{ - PG_LWGEOM *geom1; - PG_LWGEOM *geom2; - JTSGeometry *g1,*g2; - bool result; - BOX2DFLOAT4 box1, box2; - -#ifdef PROFILE - profstart(PROF_QRUN); -#endif - - geom1 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - geom2 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); - - errorIfJTSGeometryCollection(geom1,geom2); - errorIfSRIDMismatch(pglwgeom_getSRID(geom1), pglwgeom_getSRID(geom2)); - - /* - * short-circuit 1: if geom2 bounding box does not overlap - * geom1 bounding box we can prematurely return FALSE. - * Do the test IFF BOUNDING BOX AVAILABLE. - */ - if ( getbox2d_p(SERIALIZED_FORM(geom1), &box1) && - getbox2d_p(SERIALIZED_FORM(geom2), &box2) ) - { - if ( box2.xmax < box1.xmin ) PG_RETURN_BOOL(FALSE); - if ( box2.xmin > box1.xmax ) PG_RETURN_BOOL(FALSE); - if ( box2.ymax < box1.ymin ) PG_RETURN_BOOL(FALSE); - if ( box2.ymin > box2.ymax ) PG_RETURN_BOOL(FALSE); - } - - initJTS(lwnotice); - -#ifdef PROFILE - profstart(PROF_P2G1); -#endif - g1 = POSTGIS2JTS(geom1); -#ifdef PROFILE - profstop(PROF_P2G1); -#endif -#ifdef PROFILE - profstart(PROF_P2G2); -#endif - g2 = POSTGIS2JTS(geom2); -#ifdef PROFILE - profstop(PROF_P2G2); -#endif - -#ifdef PROFILE - profstart(PROF_GRUN); -#endif - result = JTSrelateOverlaps(g1,g2); -#ifdef PROFILE - profstop(PROF_GRUN); -#endif - - finishJTS(); - if (result == 2) - { - lwerror("JTS overlaps() threw an error!"); - PG_RETURN_NULL(); //never get here - } - -#ifdef PROFILE - profstop(PROF_QRUN); - profreport("jts",geom1, geom2, NULL); -#endif - - PG_FREE_IF_COPY(geom1, 0); - PG_FREE_IF_COPY(geom2, 1); - - PG_RETURN_BOOL(result); -} - - - -PG_FUNCTION_INFO_V1(contains); -Datum contains(PG_FUNCTION_ARGS) -{ - PG_LWGEOM *geom1; - PG_LWGEOM *geom2; - JTSGeometry *g1,*g2; - bool result; - BOX2DFLOAT4 box1, box2; - -#ifdef PROFILE - profstart(PROF_QRUN); -#endif - - geom1 = (PG_LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - geom2 = (PG_LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); - - errorIfJTSGeometryCollection(geom1,geom2); - errorIfSRIDMismatch(pglwgeom_getSRID(geom1), pglwgeom_getSRID(geom2)); - - /* - * short-circuit 1: if geom2 bounding box is not completely inside - * geom1 bounding box we can prematurely return FALSE. - * Do the test IFF BOUNDING BOX AVAILABLE. - */ - if ( getbox2d_p(SERIALIZED_FORM(geom1), &box1) && - getbox2d_p(SERIALIZED_FORM(geom2), &box2) ) - { - if ( box2.xmin < box1.xmin ) PG_RETURN_BOOL(FALSE); - if ( box2.xmax > box1.xmax ) PG_RETURN_BOOL(FALSE); - if ( box2.ymin < box1.ymin ) PG_RETURN_BOOL(FALSE); - if ( box2.ymax > box1.ymax ) PG_RETURN_BOOL(FALSE); - } - - initJTS(lwnotice); - -#ifdef PROFILE - profstart(PROF_P2G1); -#endif - g1 = POSTGIS2JTS(geom1); -#ifdef PROFILE - profstop(PROF_P2G1); -#endif -#ifdef PROFILE - profstart(PROF_P2G2); -#endif - g2 = POSTGIS2JTS(geom2); -#ifdef PROFILE - profstop(PROF_P2G2); -#endif - -#ifdef PROFILE - profstart(PROF_GRUN); -#endif - result = JTSrelateContains(g1,g2); -#ifdef PROFILE - profstop(PROF_GRUN); -#endif - - finishJTS(); - - if (result == 2) - { - elog(ERROR,"JTS contains() threw an error!"); - PG_RETURN_NULL(); //never get here - } - -#ifdef PROFILE - profstop(PROF_QRUN); - profreport("jts",geom1, geom2, NULL); -#endif - - PG_FREE_IF_COPY(geom1, 0); - PG_FREE_IF_COPY(geom2, 1); - - PG_RETURN_BOOL(result); -} - -/* - * Described at - * http://lin-ear-th-inking.blogspot.com/2007/06/subtleties-of-ogc-covers-spatial.html - */ -PG_FUNCTION_INFO_V1(covers); -Datum covers(PG_FUNCTION_ARGS) -{ - PG_LWGEOM *geom1; - PG_LWGEOM *geom2; - JTSGeometry *g1,*g2; - bool result; - BOX2DFLOAT4 box1, box2; - char *patt = "******FF*"; - -#ifdef PROFILE - profstart(PROF_QRUN); -#endif - - geom1 = (PG_LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - geom2 = (PG_LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); - - errorIfJTSGeometryCollection(geom1,geom2); - errorIfSRIDMismatch(pglwgeom_getSRID(geom1), pglwgeom_getSRID(geom2)); - - /* - * short-circuit 1: if geom2 bounding box is not completely inside - * geom1 bounding box we can prematurely return FALSE. - * Do the test IFF BOUNDING BOX AVAILABLE. - */ - if ( getbox2d_p(SERIALIZED_FORM(geom1), &box1) && - getbox2d_p(SERIALIZED_FORM(geom2), &box2) ) - { - if ( box2.xmin < box1.xmin ) PG_RETURN_BOOL(FALSE); - if ( box2.xmax > box1.xmax ) PG_RETURN_BOOL(FALSE); - if ( box2.ymin < box1.ymin ) PG_RETURN_BOOL(FALSE); - if ( box2.ymax > box1.ymax ) PG_RETURN_BOOL(FALSE); - } - - initJTS(lwnotice); - -#ifdef PROFILE - profstart(PROF_P2G1); -#endif - g1 = POSTGIS2JTS(geom1); -#ifdef PROFILE - profstop(PROF_P2G1); -#endif -#ifdef PROFILE - profstart(PROF_P2G2); -#endif - g2 = POSTGIS2JTS(geom2); -#ifdef PROFILE - profstop(PROF_P2G2); -#endif - -#ifdef PROFILE - profstart(PROF_GRUN); -#endif - result = JTSrelatePattern(g1,g2,patt); -#ifdef PROFILE - profstop(PROF_GRUN); -#endif - - finishJTS(); - - if (result == 2) - { - elog(ERROR,"JTS covers() threw an error!"); - PG_RETURN_NULL(); /* never get here */ - } - -#ifdef PROFILE - profstop(PROF_QRUN); - profreport("geos",geom1, geom2, NULL); -#endif - - PG_FREE_IF_COPY(geom1, 0); - PG_FREE_IF_COPY(geom2, 1); - - PG_RETURN_BOOL(result); -} - -PG_FUNCTION_INFO_V1(within); -Datum within(PG_FUNCTION_ARGS) -{ - PG_LWGEOM *geom1; - PG_LWGEOM *geom2; - JTSGeometry *g1,*g2; - bool result; - BOX2DFLOAT4 box1, box2; - -#ifdef PROFILE - profstart(PROF_QRUN); -#endif - - geom1 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - geom2 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); - - errorIfJTSGeometryCollection(geom1,geom2); - errorIfSRIDMismatch(pglwgeom_getSRID(geom1), pglwgeom_getSRID(geom2)); - - /* - * short-circuit 1: if geom1 bounding box is not completely inside - * geom2 bounding box we can prematurely return FALSE. - * Do the test IFF BOUNDING BOX AVAILABLE. - */ - if ( getbox2d_p(SERIALIZED_FORM(geom1), &box1) && - getbox2d_p(SERIALIZED_FORM(geom2), &box2) ) - { - if ( box1.xmin < box2.xmin ) PG_RETURN_BOOL(FALSE); - if ( box1.xmax > box2.xmax ) PG_RETURN_BOOL(FALSE); - if ( box1.ymin < box2.ymin ) PG_RETURN_BOOL(FALSE); - if ( box1.ymax > box2.ymax ) PG_RETURN_BOOL(FALSE); - } - - initJTS(lwnotice); - -#ifdef PROFILE - profstart(PROF_P2G1); -#endif - g1 = POSTGIS2JTS(geom1); -#ifdef PROFILE - profstop(PROF_P2G1); -#endif -#ifdef PROFILE - profstart(PROF_P2G2); -#endif - g2 = POSTGIS2JTS(geom2); -#ifdef PROFILE - profstop(PROF_P2G2); -#endif - -#ifdef PROFILE - profstart(PROF_GRUN); -#endif - result = JTSrelateWithin(g1,g2); -#ifdef PROFILE - profstop(PROF_GRUN); -#endif - - finishJTS(); - - if (result == 2) - { - lwerror("JTS within() threw an error!"); - PG_RETURN_NULL(); //never get here - } - -#ifdef PROFILE - profstop(PROF_QRUN); - profreport("jts",geom1, geom2, NULL); -#endif - - PG_FREE_IF_COPY(geom1, 0); - PG_FREE_IF_COPY(geom2, 1); - - PG_RETURN_BOOL(result); -} - -/* - * Described at: - * http://lin-ear-th-inking.blogspot.com/2007/06/subtleties-of-ogc-covers-spatial.html - */ -PG_FUNCTION_INFO_V1(coveredby); -Datum coveredby(PG_FUNCTION_ARGS) -{ - PG_LWGEOM *geom1; - PG_LWGEOM *geom2; - JTSGeometry *g1,*g2; - bool result; - BOX2DFLOAT4 box1, box2; - char *patt = "**F**F***"; - -#ifdef PROFILE - profstart(PROF_QRUN); -#endif - - geom1 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - geom2 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); - - errorIfJTSGeometryCollection(geom1,geom2); - errorIfSRIDMismatch(pglwgeom_getSRID(geom1), pglwgeom_getSRID(geom2)); - - /* - * short-circuit 1: if geom1 bounding box is not completely inside - * geom2 bounding box we can prematurely return FALSE. - * Do the test IFF BOUNDING BOX AVAILABLE. - */ - if ( getbox2d_p(SERIALIZED_FORM(geom1), &box1) && - getbox2d_p(SERIALIZED_FORM(geom2), &box2) ) - { - if ( box1.xmin < box2.xmin ) PG_RETURN_BOOL(FALSE); - if ( box1.xmax > box2.xmax ) PG_RETURN_BOOL(FALSE); - if ( box1.ymin < box2.ymin ) PG_RETURN_BOOL(FALSE); - if ( box1.ymax > box2.ymax ) PG_RETURN_BOOL(FALSE); - -#ifdef PGIS_DEBUG - lwnotice("bounding box short-circuit missed."); -#endif - } - initJTS(lwnotice); - -#ifdef PROFILE - profstart(PROF_P2G1); -#endif - g1 = POSTGIS2JTS(geom1); -#ifdef PROFILE - profstop(PROF_P2G1); -#endif -#ifdef PROFILE - profstart(PROF_P2G2); -#endif - g2 = POSTGIS2JTS(geom2); -#ifdef PROFILE - profstop(PROF_P2G2); -#endif - -#ifdef PROFILE - profstart(PROF_GRUN); -#endif - result = JTSrelatePattern(g1,g2,patt); -#ifdef PROFILE - profstop(PROF_GRUN); -#endif - - finishJTS(); - - if (result == 2) - { - elog(ERROR,"JTS coveredby() threw an error!"); - PG_RETURN_NULL(); /* never get here */ - } - -#ifdef PROFILE - profstop(PROF_QRUN); - profreport("geos",geom1, geom2, NULL); -#endif - - PG_FREE_IF_COPY(geom1, 0); - PG_FREE_IF_COPY(geom2, 1); - - PG_RETURN_BOOL(result); -} - -PG_FUNCTION_INFO_V1(crosses); -Datum crosses(PG_FUNCTION_ARGS) -{ - PG_LWGEOM *geom1; - PG_LWGEOM *geom2; - JTSGeometry *g1,*g2; - bool result; - BOX2DFLOAT4 box1, box2; - -#ifdef PROFILE - profstart(PROF_QRUN); -#endif - - geom1 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - geom2 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); - - errorIfJTSGeometryCollection(geom1,geom2); - errorIfSRIDMismatch(pglwgeom_getSRID(geom1), pglwgeom_getSRID(geom2)); - - /* - * short-circuit 1: if geom2 bounding box does not overlap - * geom1 bounding box we can prematurely return FALSE. - * Do the test IFF BOUNDING BOX AVAILABLE. - */ - if ( getbox2d_p(SERIALIZED_FORM(geom1), &box1) && - getbox2d_p(SERIALIZED_FORM(geom2), &box2) ) - { - if ( box2.xmax < box1.xmin ) PG_RETURN_BOOL(FALSE); - if ( box2.xmin > box1.xmax ) PG_RETURN_BOOL(FALSE); - if ( box2.ymax < box1.ymin ) PG_RETURN_BOOL(FALSE); - if ( box2.ymin > box2.ymax ) PG_RETURN_BOOL(FALSE); - } - - initJTS(lwnotice); - -#ifdef PROFILE - profstart(PROF_P2G1); -#endif - g1 = POSTGIS2JTS(geom1); -#ifdef PROFILE - profstop(PROF_P2G1); -#endif -#ifdef PROFILE - profstart(PROF_P2G2); -#endif - g2 = POSTGIS2JTS(geom2); -#ifdef PROFILE - profstop(PROF_P2G2); -#endif - -#ifdef PROFILE - profstart(PROF_GRUN); -#endif - result = JTSrelateCrosses(g1,g2); -#ifdef PROFILE - profstop(PROF_GRUN); -#endif - - finishJTS(); - - if (result == 2) - { - lwerror("JTS crosses() threw an error!"); - PG_RETURN_NULL(); //never get here - } - -#ifdef PROFILE - profstop(PROF_QRUN); - profreport("jts",geom1, geom2, NULL); -#endif - - PG_FREE_IF_COPY(geom1, 0); - PG_FREE_IF_COPY(geom2, 1); - - PG_RETURN_BOOL(result); -} - -PG_FUNCTION_INFO_V1(intersects_reprecated); -Datum intersects_reprecated(PG_FUNCTION_ARGS) -{ - PG_LWGEOM *geom1; - PG_LWGEOM *geom2; - bool result; - BOX2DFLOAT4 box1, box2; - MemoryContext oldContext; - PREPARED_GEOMETRY_CACHE *cache = NULL; - JTSPrepGeometry *preparedGeom = NULL; - JTSGeometry *jtsGeom = NULL; - int i, length; - uchar *serialized; - -#ifdef PGIS_DEBUG_CALLS - lwnotice("intersects (prepared jts geometry) called"); -#endif - - geom1 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - geom2 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); - - errorIfJTSGeometryCollection(geom1,geom2); - errorIfSRIDMismatch(pglwgeom_getSRID(geom1), pglwgeom_getSRID(geom2)); - - /* - * short-circuit 1: if geom2 bounding box does not overlap - * geom1 bounding box, we can prematurely return FALSE. - * Do the test IFF BOUNDING BOX AVAILABLE. - */ - if(getbox2d_p(SERIALIZED_FORM(geom1), &box1) && - getbox2d_p(SERIALIZED_FORM(geom2), &box2)) - { - if(box2.xmax < box1.xmin) PG_RETURN_BOOL(FALSE); - if(box2.xmin > box1.xmax) PG_RETURN_BOOL(FALSE); - if(box2.ymax < box1.ymin) PG_RETURN_BOOL(FALSE); - if(box2.ymin > box1.ymax) PG_RETURN_BOOL(FALSE); - } - - initJTS(lwnotice); - - /* - * Any memory allocation that must survive beyond this function call - * must be made in the function context. The terminology is a touch - * confusing. The function context will persist across all calls to - * this function within the currently running query. - */ - oldContext = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt); - /* - * Find the cache. If there is none, create it. - */ - -#ifndef DISABLE_CACHE - cache = fcinfo->flinfo->fn_extra; -#endif - -#ifdef PGIS_DEBUG - lwnotice("intersects: cache retrieved %p", cache); -#endif - if(!cache) - { -#ifdef PGIS_DEBUG - lwnotice("intersects: no cache found. Creating one."); -#endif - cache = lwalloc(sizeof(PREPARED_GEOMETRY_CACHE)); - preparedGeom = JTSPrepareGeometry(POSTGIS2JTS(geom1)); - - JTSPutLHSCache(preparedGeom); - length = lwgeom_size(SERIALIZED_FORM(geom1)); - cache->serializedGeomA = lwalloc(length); - memcpy(cache->serializedGeomA, SERIALIZED_FORM(geom1), length); - jtsGeom = POSTGIS2JTS(geom2); - JTSPutRHSCache(JTSPrepareGeometry(jtsGeom)); - length = lwgeom_size(SERIALIZED_FORM(geom2)); - cache->serializedGeomB = lwalloc(length); - memcpy(cache->serializedGeomB, SERIALIZED_FORM(geom2), length); - fcinfo->flinfo->fn_extra = cache; -#ifdef PGIS_DEBUG - lwnotice("Cache created containing geoms:"); -#endif - } - /* - * There is a cache. We must determine which geometry, if either, - * is found in the cache. - */ - else - { -#ifdef PGIS_DEBUG - lwnotice("intersects: checking cache"); -#endif - serialized = SERIALIZED_FORM(geom1); - length = lwgeom_size(serialized); - if(lwgeom_size(cache->serializedGeomA) == length) - { - for(i = 0; i < length; i++) - { - uchar a = serialized[i]; - uchar b = cache->serializedGeomA[i]; - if(a != b) - break; - } - if(i >= length) - { -#ifdef PGIS_DEBUG - lwnotice("intersects: LHS geom found in cache."); -#endif - preparedGeom = JTSGetLHSCache(); - jtsGeom = POSTGIS2JTS(geom2); -#ifdef PGIS_DEBUG - lwnotice("Cache hit, geom:"); - lwnotice("preparedGeom %p, jtsGeom %p", - preparedGeom, jtsGeom); -#endif - } - } - - serialized = SERIALIZED_FORM(geom2); - length = lwgeom_size(serialized); - if(!preparedGeom && lwgeom_size(cache->serializedGeomB) == length) - { - for(i = 0; i < length; i++) - { - uchar a = serialized[i]; - uchar b = cache->serializedGeomB[i]; - if(a != b) - break; - } - if(i >= length) - { -#ifdef PGIS_DEBUG - lwnotice("intersects: RHS geom found in cache."); -#endif - preparedGeom = JTSGetRHSCache(); - jtsGeom = POSTGIS2JTS(geom1); -#ifdef PGIS_DEBUG - lwnotice("Cache hit, geom:"); - lwnotice("preparedGeom %p, jtsGeom %p", - preparedGeom, jtsGeom); -#endif - } - } - - if(!preparedGeom) - { -#ifdef PGIS_DEBUG - lwnotice("intersects: cache miss."); -#endif - if(cache->serializedGeomA) - lwfree(cache->serializedGeomA); - preparedGeom = JTSPrepareGeometry(POSTGIS2JTS(geom1)); - JTSPutLHSCache(preparedGeom); - length = lwgeom_size(SERIALIZED_FORM(geom1)); - cache->serializedGeomA = lwalloc(length); - memcpy(cache->serializedGeomA, - SERIALIZED_FORM(geom1), length); - - if(cache->serializedGeomB) - lwfree(cache->serializedGeomB); - jtsGeom = POSTGIS2JTS(geom2); - JTSPutRHSCache(JTSPrepareGeometry(jtsGeom)); - length = lwgeom_size(SERIALIZED_FORM(geom2)); - cache->serializedGeomB = lwalloc(length); - memcpy(cache->serializedGeomB, - SERIALIZED_FORM(geom2), length); - } - } - MemoryContextSwitchTo(oldContext); -#ifdef PGIS_DEBUG - lwnotice("intersects: prepared-%p, geom-%p", preparedGeom, jtsGeom); - JTSPrintPreparedGeometry(preparedGeom); -#endif - - if(!preparedGeom || !jtsGeom) - { - - lwnotice("intersects error: Unable to prepare geometery (%p, %p)", preparedGeom, jtsGeom); - result = JTSrelateIntersects(POSTGIS2JTS(geom1), - POSTGIS2JTS(geom2)); - if (result == 2) - { - lwerror("JTS intersects() threw an error!"); - PG_FREE_IF_COPY(geom1, 0); - PG_FREE_IF_COPY(geom2, 1); - PG_RETURN_NULL(); - } - - } - else - { - - result = JTSpreparedIntersects(preparedGeom, jtsGeom); - - /* - finishJTS(); - */ - if (result == 2) - { - lwerror("JTS intersects() threw an error!"); - PG_FREE_IF_COPY(geom1, 0); - PG_FREE_IF_COPY(geom2, 1); - PG_RETURN_NULL(); //never get here - } - } - - PG_FREE_IF_COPY(geom1, 0); - PG_FREE_IF_COPY(geom2, 1); - -#ifdef PGIS_DEBUG_CALLS - lwnotice("intersects() returning."); -#endif - - PG_RETURN_BOOL(result); -} - - - -PG_FUNCTION_INFO_V1(intersects); -Datum intersects(PG_FUNCTION_ARGS) -{ - PG_LWGEOM *geom1; - PG_LWGEOM *geom2; - JTSGeometry *g1; - JTSGeometry *g2; - bool result; - BOX2DFLOAT4 box1, box2; - -#ifdef PROFILE - profstart(PROF_QRUN); -#endif - - geom1 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - geom2 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); - - errorIfJTSGeometryCollection(geom1,geom2); - errorIfSRIDMismatch(pglwgeom_getSRID(geom1), pglwgeom_getSRID(geom2)); - - /* - * short-circuit 1: if geom2 bounding box does not overlap - * geom1 bounding box we can prematurely return FALSE. - * Do the test IFF BOUNDING BOX AVAILABLE. - */ - if ( getbox2d_p(SERIALIZED_FORM(geom1), &box1) && - getbox2d_p(SERIALIZED_FORM(geom2), &box2) ) - { - if ( box2.xmax < box1.xmin ) PG_RETURN_BOOL(FALSE); - if ( box2.xmin > box1.xmax ) PG_RETURN_BOOL(FALSE); - if ( box2.ymax < box1.ymin ) PG_RETURN_BOOL(FALSE); - if ( box2.ymin > box2.ymax ) PG_RETURN_BOOL(FALSE); - } - - initJTS(lwnotice); - -#ifdef PROFILE - profstart(PROF_P2G1); -#endif - g1 = POSTGIS2JTS(geom1 ); -#ifdef PROFILE - profstop(PROF_P2G1); -#endif -#ifdef PROFILE - profstart(PROF_P2G2); -#endif - g2 = POSTGIS2JTS(geom2 ); -#ifdef PROFILE - profstop(PROF_P2G2); -#endif - -#ifdef PROFILE - profstart(PROF_GRUN); -#endif - result = JTSrelateIntersects(g1,g2); -#ifdef PROFILE - profstop(PROF_GRUN); -#endif - finishJTS(); - if (result == 2) - { - lwerror("JTS intersects() threw an error!"); - PG_RETURN_NULL(); //never get here - } - -#ifdef PROFILE - profstop(PROF_QRUN); - profreport("intr",geom1, geom2, NULL); -#endif - - PG_FREE_IF_COPY(geom1, 0); - PG_FREE_IF_COPY(geom2, 1); - - PG_RETURN_BOOL(result); -} - - -PG_FUNCTION_INFO_V1(touches); -Datum touches(PG_FUNCTION_ARGS) -{ - PG_LWGEOM *geom1; - PG_LWGEOM *geom2; - JTSGeometry *g1,*g2; - bool result; - BOX2DFLOAT4 box1, box2; - -#ifdef PROFILE - profstart(PROF_QRUN); -#endif - - geom1 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - geom2 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); - - errorIfJTSGeometryCollection(geom1,geom2); - errorIfSRIDMismatch(pglwgeom_getSRID(geom1), pglwgeom_getSRID(geom2)); - - /* - * short-circuit 1: if geom2 bounding box does not overlap - * geom1 bounding box we can prematurely return FALSE. - * Do the test IFF BOUNDING BOX AVAILABLE. - */ - if ( getbox2d_p(SERIALIZED_FORM(geom1), &box1) && - getbox2d_p(SERIALIZED_FORM(geom2), &box2) ) - { - if ( box2.xmax < box1.xmin ) PG_RETURN_BOOL(FALSE); - if ( box2.xmin > box1.xmax ) PG_RETURN_BOOL(FALSE); - if ( box2.ymax < box1.ymin ) PG_RETURN_BOOL(FALSE); - if ( box2.ymin > box2.ymax ) PG_RETURN_BOOL(FALSE); - } - - initJTS(lwnotice); - -#ifdef PROFILE - profstart(PROF_P2G1); -#endif - g1 = POSTGIS2JTS(geom1 ); -#ifdef PROFILE - profstop(PROF_P2G1); -#endif -#ifdef PROFILE - profstart(PROF_P2G2); -#endif - g2 = POSTGIS2JTS(geom2 ); -#ifdef PROFILE - profstop(PROF_P2G2); -#endif - -#ifdef PROFILE - profstart(PROF_GRUN); -#endif - result = JTSrelateTouches(g1,g2); -#ifdef PROFILE - profstop(PROF_GRUN); -#endif - - finishJTS(); - - if (result == 2) - { - lwerror("JTS touches() threw an error!"); - PG_RETURN_NULL(); //never get here - } - -#ifdef PROFILE - profstop(PROF_QRUN); - profreport("jts",geom1, geom2, NULL); -#endif - - PG_FREE_IF_COPY(geom1, 0); - PG_FREE_IF_COPY(geom2, 1); - - PG_RETURN_BOOL(result); -} - - -PG_FUNCTION_INFO_V1(disjoint); -Datum disjoint(PG_FUNCTION_ARGS) -{ - PG_LWGEOM *geom1; - PG_LWGEOM *geom2; - JTSGeometry *g1,*g2; - bool result; - BOX2DFLOAT4 box1, box2; - -#ifdef PROFILE - profstart(PROF_QRUN); -#endif - - geom1 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - geom2 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); - - errorIfJTSGeometryCollection(geom1,geom2); - errorIfSRIDMismatch(pglwgeom_getSRID(geom1), pglwgeom_getSRID(geom2)); - - /* - * short-circuit 1: if geom2 bounding box does not overlap - * geom1 bounding box we can prematurely return TRUE. - * Do the test IFF BOUNDING BOX AVAILABLE. - */ - if ( getbox2d_p(SERIALIZED_FORM(geom1), &box1) && - getbox2d_p(SERIALIZED_FORM(geom2), &box2) ) - { - if ( box2.xmax < box1.xmin ) PG_RETURN_BOOL(TRUE); - if ( box2.xmin > box1.xmax ) PG_RETURN_BOOL(TRUE); - if ( box2.ymax < box1.ymin ) PG_RETURN_BOOL(TRUE); - if ( box2.ymin > box2.ymax ) PG_RETURN_BOOL(TRUE); - } - - initJTS(lwnotice); - -#ifdef PROFILE - profstart(PROF_P2G1); -#endif - g1 = POSTGIS2JTS(geom1); -#ifdef PROFILE - profstop(PROF_P2G1); -#endif -#ifdef PROFILE - profstart(PROF_P2G2); -#endif - g2 = POSTGIS2JTS(geom2); -#ifdef PROFILE - profstop(PROF_P2G2); -#endif - -#ifdef PROFILE - profstart(PROF_GRUN); -#endif - result = JTSrelateDisjoint(g1,g2); -#ifdef PROFILE - profstop(PROF_GRUN); -#endif - - finishJTS(); - - if (result == 2) - { - lwerror("JTS disjoin() threw an error!"); - PG_RETURN_NULL(); //never get here - } - -#ifdef PROFILE - profstop(PROF_QRUN); - profreport("jts",geom1, geom2, NULL); -#endif - - PG_FREE_IF_COPY(geom1, 0); - PG_FREE_IF_COPY(geom2, 1); - - PG_RETURN_BOOL(result); -} - - -PG_FUNCTION_INFO_V1(relate_pattern); -Datum relate_pattern(PG_FUNCTION_ARGS) -{ - PG_LWGEOM *geom1; - PG_LWGEOM *geom2; - char *patt; - bool result; - JTSGeometry *g1,*g2; - -#ifdef PROFILE - profstart(PROF_QRUN); -#endif - - geom1 = (PG_LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - geom2 = (PG_LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); - - errorIfJTSGeometryCollection(geom1,geom2); - errorIfSRIDMismatch(pglwgeom_getSRID(geom1), pglwgeom_getSRID(geom2)); - - initJTS(lwnotice); - -#ifdef PROFILE - profstart(PROF_P2G1); -#endif - g1 = POSTGIS2JTS(geom1); -#ifdef PROFILE - profstop(PROF_P2G1); -#endif -#ifdef PROFILE - profstart(PROF_P2G2); -#endif - g2 = POSTGIS2JTS(geom2); -#ifdef PROFILE - profstop(PROF_P2G2); -#endif - - patt = DatumGetCString(DirectFunctionCall1(textout, - PointerGetDatum(PG_GETARG_DATUM(2)))); - -#ifdef PROFILE - profstart(PROF_GRUN); -#endif - result = JTSrelatePattern(g1,g2,patt); -#ifdef PROFILE - profstop(PROF_GRUN); -#endif - - finishJTS(); - pfree(patt); - - if (result == 2) - { - elog(ERROR,"JTS relate_pattern() threw an error!"); - PG_RETURN_NULL(); //never get here - } - -#ifdef PROFILE - profstop(PROF_QRUN); - profreport("jts",geom1, geom2, NULL); -#endif - - PG_FREE_IF_COPY(geom1, 0); - PG_FREE_IF_COPY(geom2, 1); - - PG_RETURN_BOOL(result); -} - - - -PG_FUNCTION_INFO_V1(relate_full); -Datum relate_full(PG_FUNCTION_ARGS) -{ - PG_LWGEOM *geom1; - PG_LWGEOM *geom2; - JTSGeometry *g1,*g2; - char *relate_str; - int len; - text *result; - -#ifdef PROFILE - profstart(PROF_QRUN); -#endif - -//elog(NOTICE,"in relate_full()"); - - geom1 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - geom2 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); - - errorIfJTSGeometryCollection(geom1,geom2); - errorIfSRIDMismatch(pglwgeom_getSRID(geom1), pglwgeom_getSRID(geom2)); - - - initJTS(lwnotice); - -//elog(NOTICE,"JTS init()"); - -#ifdef PROFILE - profstart(PROF_P2G1); -#endif - g1 = POSTGIS2JTS(geom1 ); -#ifdef PROFILE - profstop(PROF_P2G1); -#endif -#ifdef PROFILE - profstart(PROF_P2G2); -#endif - g2 = POSTGIS2JTS(geom2 ); -#ifdef PROFILE - profstop(PROF_P2G2); -#endif - -//elog(NOTICE,"constructed geometries "); - - if ((g1==NULL) || (g2 == NULL)) - { - finishJTS(); - lwerror("g1 or g2 are null"); - } - -//elog(NOTICE,JTSasText(g1)); -//elog(NOTICE,JTSasText(g2)); - -//elog(NOTICE,"valid g1 = %i", JTSisvalid(g1)); -//elog(NOTICE,"valid g2 = %i",JTSisvalid(g2)); - -//elog(NOTICE,"about to relate()"); - - -#ifdef PROFILE - profstart(PROF_GRUN); -#endif - relate_str = JTSrelate(g1, g2); -#ifdef PROFILE - profstop(PROF_GRUN); -#endif - -//lwnotice("finished relate()"); - - g1=g2=NULL; // for GC - finishJTS(); - - if (relate_str == NULL) - { - lwerror("JTS relate() threw an error!"); - PG_RETURN_NULL(); //never get here - } - - len = strlen(relate_str) + VARHDRSZ; - - result= palloc(len); - SET_VARSIZE(result, len); - //*((int *) result) = len; - - memcpy(VARDATA(result), relate_str, len-VARHDRSZ); - - free(relate_str); - -#ifdef PROFILE - profstop(PROF_QRUN); - profreport("jts",geom1, geom2, NULL); -#endif - - PG_FREE_IF_COPY(geom1, 0); - PG_FREE_IF_COPY(geom2, 1); - - PG_RETURN_POINTER(result); -} - -//============================== - -PG_FUNCTION_INFO_V1(geomequals); -Datum geomequals(PG_FUNCTION_ARGS) -{ - PG_LWGEOM *geom1; - PG_LWGEOM *geom2; - JTSGeometry *g1,*g2; - bool result; - BOX2DFLOAT4 box1, box2; - -#ifdef PROFILE - profstart(PROF_QRUN); -#endif - - geom1 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - geom2 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); - - errorIfJTSGeometryCollection(geom1,geom2); - errorIfSRIDMismatch(pglwgeom_getSRID(geom1), pglwgeom_getSRID(geom2)); - - /* - * short-circuit 1: if geom2 bounding box does not equal - * geom1 bounding box we can prematurely return FALSE. - * Do the test IFF BOUNDING BOX AVAILABLE. - */ - if ( getbox2d_p(SERIALIZED_FORM(geom1), &box1) && - getbox2d_p(SERIALIZED_FORM(geom2), &box2) ) - { - if ( box2.xmax != box1.xmax ) PG_RETURN_BOOL(FALSE); - if ( box2.xmin != box1.xmin ) PG_RETURN_BOOL(FALSE); - if ( box2.ymax != box1.ymax ) PG_RETURN_BOOL(FALSE); - if ( box2.ymin != box2.ymin ) PG_RETURN_BOOL(FALSE); - } - - initJTS(lwnotice); - -#ifdef PROFILE - profstart(PROF_P2G1); -#endif - g1 = POSTGIS2JTS(geom1); -#ifdef PROFILE - profstop(PROF_P2G1); -#endif -#ifdef PROFILE - profstart(PROF_P2G2); -#endif - g2 = POSTGIS2JTS(geom2); -#ifdef PROFILE - profstop(PROF_P2G2); -#endif - -#ifdef PROFILE - profstart(PROF_GRUN); -#endif - result = JTSequals(g1,g2); -#ifdef PROFILE - profstop(PROF_GRUN); -#endif - - finishJTS(); - - if (result == 2) - { - lwerror("JTS equals() threw an error!"); - PG_RETURN_NULL(); //never get here - } - -#ifdef PROFILE - profstop(PROF_QRUN); - profreport("jts",geom1, geom2, NULL); -#endif - - PG_FREE_IF_COPY(geom1, 0); - PG_FREE_IF_COPY(geom2, 1); - - PG_RETURN_BOOL(result); -} - -PG_FUNCTION_INFO_V1(issimple); -Datum issimple(PG_FUNCTION_ARGS) -{ - PG_LWGEOM *geom; - JTSGeometry *g1; - int result; - -#ifdef PROFILE - profstart(PROF_QRUN); -#endif - - geom = (PG_LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - - if (lwgeom_getnumgeometries(SERIALIZED_FORM(geom)) == 0) - PG_RETURN_BOOL(true); - - initJTS(lwnotice); - - //elog(NOTICE,"JTS init()"); - -#ifdef PROFILE - profstart(PROF_P2G1); -#endif - g1 = POSTGIS2JTS(geom); -#ifdef PROFILE - profstop(PROF_P2G1); -#endif - -#ifdef PROFILE - profstart(PROF_GRUN); -#endif - result = JTSisSimple(g1); -#ifdef PROFILE - profstop(PROF_GRUN); -#endif - - finishJTS(); - - if (result == 2) - { - elog(ERROR,"JTS issimple() threw an error!"); - PG_RETURN_NULL(); //never get here - } - -#ifdef PROFILE - profstop(PROF_QRUN); - profreport("jts",geom, NULL, NULL); -#endif - - PG_FREE_IF_COPY(geom, 0); - - PG_RETURN_BOOL(result); -} - -PG_FUNCTION_INFO_V1(isring); -Datum isring(PG_FUNCTION_ARGS) -{ - PG_LWGEOM *geom; - JTSGeometry *g1; - int result; - -#ifdef PROFILE - profstart(PROF_QRUN); -#endif - - geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - - if (lwgeom_getType(geom->type) != LINETYPE) - { - elog(ERROR,"isring() should only be called on a LINE"); - } - - if (lwgeom_getnumgeometries(SERIALIZED_FORM(geom)) == 0) - PG_RETURN_BOOL(false); - - initJTS(lwnotice); - - //elog(NOTICE,"JTS init()"); - -#ifdef PROFILE - profstart(PROF_P2G1); -#endif - g1 = POSTGIS2JTS(geom ); -#ifdef PROFILE - profstop(PROF_P2G1); -#endif - -#ifdef PROFILE - profstart(PROF_GRUN); -#endif - result = JTSisRing(g1); -#ifdef PROFILE - profstop(PROF_GRUN); -#endif - - finishJTS(); - - if (result == 2) - { - lwerror("JTS isring() threw an error!"); - PG_RETURN_NULL(); //never get here - } - -#ifdef PROFILE - profstop(PROF_QRUN); - profreport("jts",geom, NULL, NULL); -#endif - - PG_FREE_IF_COPY(geom, 0); - - PG_RETURN_BOOL(result); -} - - - -//= JTS <=> POSTGIS CONVERSION ========================= - -//-----=JTS2POSTGIS= - -// Return a LWPOINT from a JTS Point. -LWPOINT * -lwpoint_from_geometry(JTSGeometry *g, char want3d) -{ - POINTARRAY *pa; - LWPOINT *point; - POINT3D *pts; - size_t ptsize = want3d ? sizeof(POINT3DZ) : sizeof(POINT2D); - int SRID = JTSGetSRID(g); - -#ifdef PGIS_DEBUG_JTS2POSTGIS - elog(NOTICE, "lwpoint_from_geometry: point size %d", ptsize); -#endif - - // Construct point array - pa = (POINTARRAY *)lwalloc(sizeof(POINTARRAY)); - TYPE_SETZM(pa->dims, want3d, 0); - pa->npoints = 1; - - // Fill point array - pa->serialized_pointlist = lwalloc(ptsize); - pts = JTSGetCoordinates(g); - memcpy(pa->serialized_pointlist, pts, ptsize); - JTSdeleteChar( (char*) pts); - - // Construct LWPOINT - point = lwpoint_construct(SRID, NULL, pa); - - return point; -} - -// Return a LWLINE from a JTS linestring -LWLINE * -lwline_from_geometry(JTSGeometry *g, char want3d) -{ - POINTARRAY *pa; - LWLINE *line; - int npoints; - POINT3D *pts, *ip; - int ptsize = want3d ? sizeof(POINT3D) : sizeof(POINT2D); - int i; - int SRID = JTSGetSRID(g); - -#ifdef PGIS_DEBUG_JTS2POSTGIS - elog(NOTICE, "lwline_from_geometry: point size %d", ptsize); -#endif - - npoints = JTSGetNumCoordinate(g); - if (npoints <2) return NULL; - - // Construct point array - pa = (POINTARRAY *)palloc(sizeof(POINTARRAY)); - TYPE_SETZM(pa->dims, want3d, 0); - pa->npoints = npoints; - - // Fill point array - pa->serialized_pointlist = palloc(ptsize*npoints); - pts = JTSGetCoordinates(g); - for (i=0; idims, want3d, 0); - pa->npoints = npoints; - - // Fill point array - pa->serialized_pointlist = palloc(ptsize*npoints); - for (i=0; idims, want3d, 0); - pa->npoints = npoints; - - // Fill point array - pa->serialized_pointlist = palloc(ptsize*npoints); - for (i=0; itype))); -#endif - } - - ret = lwcollection_construct(type, SRID, NULL, ngeoms, geoms); - return ret; -} - -#if WKT_J2P - -// Return an LWGEOM from a JTSGeometry -LWGEOM * -JTS2LWGEOM(JTSGeometry *geom, char want3d) -{ - char *wkt; - SERIALIZED_LWGEOM *serialized_lwgeom; - PG_LWGEOM *pglwgeom; - LWGEOM *ret; - - //lwnotice("JTS2LWGEOM(WKT) called"); - - wkt = JTSasText(geom); - -#ifdef PGIS_DEBUG_JTS2POSTGIS - lwnotice("JTS2LWGEOM: wkt: %d bytes", strlen(wkt)); -#endif - - serialized_lwgeom = parse_lwgeom_wkt(wkt); - - //lwnotice("JTS2LWGEOM(WKT): wkt parsed (got pglwgeom)"); - -#ifdef PGIS_DEBUG_JTS2POSTGIS - lwnotice("JTS2LWGEOM: parsed: %s", - lwgeom_typename(TYPE_GETTYPE(pglwgeom->type))); -#endif - ret = lwgeom_deserialize(serialized_lwgeom->lwgeom); - - ret->SRID = JTSGetSRID(geom); - //lwnotice("JTS2LWGEOM: return SRID: %d", ret->SRID); - - return ret; -} - -#else // ! WKT_J2P - -// Return an LWGEOM from a JTSGeometry -LWGEOM * -JTS2LWGEOM(JTSGeometry *geom, char want3d) -{ - int type = JTSGeometryTypeId(geom) ; - bool hasZ = JTSHasZ(geom); - - //lwnotice("JTS2LWGEOM(!WKT) called"); - - if ( ! hasZ ) - { - if ( want3d ) - { - //elog(NOTICE, "JTSGeometry has no Z, won't provide one"); - want3d = 0; - } - } - -#ifdef PGIS_DEBUG_JTS2POSTGIS - lwnotice("JTS2LWGEOM: it's a %s", lwgeom_typename(type)); -#endif - switch (type) - { - /* From slower to faster.. compensation rule :) */ - - case COLLECTIONTYPE: - case MULTIPOLYGONTYPE: - case MULTILINETYPE: - case MULTIPOINTTYPE: - return (LWGEOM *)lwcollection_from_geometry(geom, want3d); - - case POLYGONTYPE: - return (LWGEOM *)lwpoly_from_geometry(geom, want3d); - - case LINETYPE: - return (LWGEOM *)lwline_from_geometry(geom, want3d); - - case POINTTYPE: - return (LWGEOM *)lwpoint_from_geometry(geom, want3d); - - default: - lwerror("JTS2LWGEOM: unknown geometry type: %d", type); - return NULL; - - } - -} - -#endif // ! WKT_J2P - - -PG_LWGEOM * -JTS2POSTGIS(JTSGeometry *geom, char want3d) -{ - LWGEOM *lwgeom; - PG_LWGEOM *result; - -#ifdef PGIS_DEBUG_JTS2POSTGIS - lwnotice("JTS2POSTGIS: called"); -#endif - - lwgeom = JTS2LWGEOM(geom, want3d); - if ( ! lwgeom ) - { - lwerror("JTS2POSTGIS: JTS2LWGEOM returned NULL"); - return NULL; - } - -#ifdef PGIS_DEBUG_JTS2POSTGIS - lwnotice("JTS2POSTGIS: JTS2LWGEOM returned a %s", lwgeom_summary(lwgeom, 0)); -#endif - - if ( is_worth_caching_lwgeom_bbox(lwgeom) ) - { - lwgeom_addBBOX(lwgeom); - } - - result = pglwgeom_serialize(lwgeom); - - return result; -} - - -//-----=POSTGIS2JTS= - -JTSGeometry *LWGEOM2JTS(LWGEOM *lwgeom); - -#if WKT_P2J - -JTSGeometry * -LWGEOM2JTS(LWGEOM *lwgeom) -{ - PG_LWGEOM *geom; - PG_LWGEOM *ogcgeom; - char *wkt, *ogcwkt, *loc; - JTSGeometry *g; - - //lwnotice("LWGEOM2JTS: WKT version"); - - geom = pglwgeom_serialize(lwgeom); - if ( ! geom ) { - lwerror("LWGEOM2JTS(WKT): couldn't serialized lwgeom"); - return NULL; - } - - /* Force to 2d */ - ogcgeom = (PG_LWGEOM *)DatumGetPointer(DirectFunctionCall1( - LWGEOM_force_2d, PointerGetDatum(geom))); - wkt = unparse_WKT(SERIALIZED_FORM(ogcgeom), lwalloc, lwfree); - - lwfree(ogcgeom); - if ( geom != ogcgeom ) lwfree(geom); - - loc = strchr(wkt,';'); - if (loc != NULL) ogcwkt = loc+1; - else ogcwkt=wkt; - - g = JTSGeometryFromWKT(ogcwkt); - JTSSetSRID(g, lwgeom->SRID); - - lwfree(wkt); -#ifdef PGIS_DEBUG_POSTGIS2JTS - lwnotice("LWGEOM2JTS: returning JTS JTSGeometry"); -#endif - return g; -} - -#else // ! WKT_P2J - -JTSGeometry * -LWGEOM2JTS(LWGEOM *lwgeom) -{ - uint32 i; - JTSGeometry **collected; - LWCOLLECTION *col; - - //lwnotice("LWGEOM2JTS: !WKT version"); - - if ( ! lwgeom ) return NULL; - -#ifdef PGIS_DEBUG_POSTGIS2JTS - lwnotice("LWGEOM2JTS: got lwgeom[%p]", lwgeom); -#endif - - switch (TYPE_GETTYPE(lwgeom->type)) - { - case POINTTYPE: -#ifdef PGIS_DEBUG_POSTGIS2JTS - lwnotice("LWGEOM2JTS: point[%p]", lwgeom); -#endif - return PostGIS2JTS_point((LWPOINT *)lwgeom); - - case LINETYPE: -#ifdef PGIS_DEBUG_POSTGIS2JTS - lwnotice("LWGEOM2JTS: line[%p]", lwgeom); -#endif - return PostGIS2JTS_linestring((LWLINE *)lwgeom); - - case POLYGONTYPE: -#ifdef PGIS_DEBUG_POSTGIS2JTS - lwnotice("LWGEOM2JTS: poly[%p]", lwgeom); -#endif - return PostGIS2JTS_polygon((LWPOLY *)lwgeom); - - case MULTIPOINTTYPE: - case MULTILINETYPE: - case MULTIPOLYGONTYPE: - case COLLECTIONTYPE: - col = (LWCOLLECTION *)lwgeom; -#ifdef PGIS_DEBUG_POSTGIS2JTS - lwnotice("LWGEOM2JTS: %s with %d subgeoms", lwgeom_typename(TYPE_GETTYPE(col->type)), col->ngeoms); -#endif - collected = (JTSGeometry **)lwalloc(sizeof(JTSGeometry *)*col->ngeoms); - for (i=0; ingeoms; i++) - { - collected[i] = LWGEOM2JTS(col->geoms[i]); - } - return PostGIS2JTS_collection(TYPE_GETTYPE(col->type), - collected, col->ngeoms, col->SRID, - TYPE_NDIMS(col->type)>2); - - case CURVETYPE: - case COMPOUNDTYPE: - case CURVEPOLYTYPE: - case MULTICURVETYPE: - case MULTISURFACETYPE: - lwerror("Exception in LWGEOM2JTS: curved geometry not supported."); - return NULL; - default: - lwerror("Unknown geometry type: %d", - TYPE_GETTYPE(lwgeom->type)); - return NULL; - } - -} - -#endif // ! WKT_P2J - -JTSGeometry * -POSTGIS2JTS(PG_LWGEOM *geom) -{ - JTSGeometry *ret; - LWGEOM *lwgeom; - -#ifdef PGIS_DEBUG_POSTGIS2JTS - lwnotice("POSTGIS2JTS: called"); -#endif - - lwgeom = lwgeom_deserialize(SERIALIZED_FORM(geom)); - if ( ! lwgeom ) - { - lwerror("POSTGIS2JTS: unable to deserialize input"); - return NULL; - } - ret = LWGEOM2JTS(lwgeom); - - lwgeom_release(lwgeom); - if ( ! ret ) { - lwerror("POSTGIS2JTS conversion failed"); - return NULL; - } -#ifdef PGIS_DEBUG_POSTGIS2JTS - lwnotice("POSTGIS2JTS: returning %p", ret); -#endif - return ret; -} - -PG_FUNCTION_INFO_V1(JTSnoop); -Datum JTSnoop(PG_FUNCTION_ARGS) -{ - PG_LWGEOM *geom; - JTSGeometry *geosgeom; - PG_LWGEOM *result; - - initJTS(lwnotice); - - geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); -#ifdef PGIS_DEBUG_CONVERTER - lwnotice("JTSnoop: IN: %s", lwgeom_summary(lwgeom_deserialize(SERIALIZED_FORM(geom)), 0)); -#endif - - geosgeom = POSTGIS2JTS(geom); - if ( ! geosgeom ) PG_RETURN_NULL(); - -#ifdef PROFILE - profstart(PROF_GRUN); - profstop(PROF_GRUN); -#endif - - result = JTS2POSTGIS(geosgeom, TYPE_NDIMS(geom->type) > 2); - - finishJTS(); - -#ifdef PGIS_DEBUG_CONVERTER - elog(NOTICE, "JTSnoop: OUT: %s", unparse_WKT(SERIALIZED_FORM(result), lwalloc, lwfree)); -#endif - - PG_FREE_IF_COPY(geom, 0); - - PG_RETURN_POINTER(result); -} - -PG_FUNCTION_INFO_V1(polygonize_garray); -Datum polygonize_garray(PG_FUNCTION_ARGS) -{ - Datum datum; - ArrayType *array; - int is3d = 0; - unsigned int nelems, i; - PG_LWGEOM *result; - JTSGeometry *geos_result; - JTSGeometry **vgeoms; - int SRID=-1; - size_t offset; -#ifdef PGIS_DEBUG - static int call=1; -#endif - -#ifdef PGIS_DEBUG - call++; -#endif - - datum = PG_GETARG_DATUM(0); - - /* Null array, null geometry (should be empty?) */ - if ( (Pointer *)datum == NULL ) PG_RETURN_NULL(); - - array = DatumGetArrayTypeP(datum); - - nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array)); - -#ifdef PGIS_DEBUG - elog(NOTICE, "polygonize_garray: number of elements: %d", nelems); -#endif - - if ( nelems == 0 ) PG_RETURN_NULL(); - - /* Ok, we really need geos now ;) */ - initJTS(lwnotice); - - vgeoms = palloc(sizeof(JTSGeometry *)*nelems); - offset = 0; - for (i=0; itype) > 2); -#ifdef PROFILE - profstop(PROF_G2P); -#endif - if (result == NULL) - { - elog(ERROR,"JTS LineMerge() threw an error (result postgis geometry formation)!"); - PG_RETURN_NULL(); //never get here - } - - //compressType(result); // convert multi* to single item if appropriate - -#ifdef PROFILE - profstop(PROF_QRUN); - profreport("jts",geom1, NULL, result); -#endif - - PG_FREE_IF_COPY(geom1, 0); - - PG_RETURN_POINTER(result); -} - -Datum GEOSnoop(PG_FUNCTION_ARGS); -PG_FUNCTION_INFO_V1(GEOSnoop); -Datum GEOSnoop(PG_FUNCTION_ARGS) -{ - elog(ERROR, "GEOS support is disabled"); - PG_RETURN_NULL(); -} - -PG_FUNCTION_INFO_V1(postgis_geos_version); -Datum postgis_geos_version(PG_FUNCTION_ARGS) -{ - PG_RETURN_NULL(); -} - -PG_FUNCTION_INFO_V1(postgis_jts_version); -Datum postgis_jts_version(PG_FUNCTION_ARGS) -{ - char *ver; - text *result; - - initJTS(lwnotice); - - ver = JTSversion(); - result = (text *) palloc(VARHDRSZ + strlen(ver)); - SET_VARSIZE(result, VARHDRSZ + strlen(ver)); - memcpy(VARDATA(result), ver, strlen(ver)); - free(ver); - - finishJTS(); - - PG_RETURN_POINTER(result); -} - -PG_FUNCTION_INFO_V1(LWGEOM_buildarea); -Datum LWGEOM_buildarea(PG_FUNCTION_ARGS) -{ - elog(ERROR,"BuildArea: operation not implemented in JTS wrapper - compile PostGIS with GEOS support"); - PG_RETURN_NULL(); // never get here -} diff --git a/lwgeom/lwgeom_jts_wrapper.cpp b/lwgeom/lwgeom_jts_wrapper.cpp deleted file mode 100644 index 725cd39ed..000000000 --- a/lwgeom/lwgeom_jts_wrapper.cpp +++ /dev/null @@ -1,1211 +0,0 @@ -#include - -#include -#include -#include - -#pragma GCC java_exceptions - -#include -#include -#include -#include -#include - -//#define DEBUG_JARRAY 1 - -using namespace com::vividsolutions::jts::geom::prep; -using namespace com::vividsolutions::jts::geom; -using namespace com::vividsolutions::jts::io; -using namespace com::vividsolutions::jts; -using namespace java::lang; -using namespace std; - -//for getting things to align properly double are on 8byte align on solaris machines, and 4bytes on intel - -//---- Definitions found in lwgeom.h (and postgis) - -#define TYPE_NDIMS(t) ((((t)&0x20)>>5)+(((t)&0x10)>>4)+2) -#define TYPE_HASZ(t) ( ((t)&0x20)>>5 ) - -typedef unsigned int uint32; -typedef int int32; - -typedef struct -{ - double xmin, ymin, zmin; - double xmax, ymax, zmax; -} BOX3D; - -typedef struct { float xmin, ymin, xmax, ymax; } BOX2DFLOAT4; - -typedef struct { double x,y,z; } POINT3D; - -typedef struct -{ - char *serialized_pointlist; - unsigned char dims; - uint32 npoints; -} POINTARRAY; - -typedef struct -{ - unsigned char type; - BOX2DFLOAT4 *bbox; - uint32 SRID; - POINTARRAY *point; // hide 2d/3d (this will be an array of 1 point) -} LWPOINT; // "light-weight point" - -// LINETYPE -typedef struct -{ - unsigned char type; - BOX2DFLOAT4 *bbox; - uint32 SRID; - POINTARRAY *points; // array of POINT3D -} LWLINE; //"light-weight line" - -// POLYGONTYPE -typedef struct -{ - unsigned char type; - BOX2DFLOAT4 *bbox; - uint32 SRID; - int nrings; - POINTARRAY **rings; // list of rings (list of points) -} LWPOLY; // "light-weight polygon" - -extern "C" int getPoint3dz_p(POINTARRAY *pa, int n, POINT3D *); - -//---- 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 - -//########################################################### - -typedef void (*noticefunc)(const char *fmt, ...); - -extern "C" char *JTSrelate(Geometry *g1, Geometry*g2); -extern "C" void initJTS(noticefunc); -extern "C" void finishJTS(void); - - -extern "C" void JTSSetSRID(Geometry *g, int SRID); -extern "C" void JTSdeleteChar(char *a); -extern "C" void JTSdeleteGeometry(Geometry *a); -extern "C" char JTSrelatePattern(Geometry *g1, Geometry*g2,char *pat); -extern "C" char JTSrelateDisjoint(Geometry *g1, Geometry*g2); -extern "C" char JTSrelateTouches(Geometry *g1, Geometry*g2); -extern "C" char JTSrelateIntersects(Geometry *g1, Geometry*g2); -extern "C" char JTSrelateCrosses(Geometry *g1, Geometry*g2); -extern "C" char JTSrelateWithin(Geometry *g1, Geometry*g2); -extern "C" char JTSrelateContains(Geometry *g1, Geometry*g2); -extern "C" char JTSrelateOverlaps(Geometry *g1, Geometry*g2); -extern "C" Geometry *JTSPolygonize(Geometry **geoms, unsigned int ngeoms); -extern "C" Geometry *JTSLineMerge(Geometry *geoms); -extern "C" char *JTSversion(); -extern "C" char *JTSjtsport(); -extern "C" int JTSGeometryTypeId(Geometry *g1); - -extern "C" char JTSpreparedIntersects(PreparedGeometry *pg, Geometry* g); -extern "C" PreparedGeometry *JTSPrepareGeometry(Geometry* g); -extern "C" void JTSgc(void); -extern "C" void JTSPrintPreparedGeometry(PreparedGeometry *pg); -extern "C" PreparedGeometry *JTSGetRHSCache(); -extern "C" PreparedGeometry *JTSGetLHSCache(); -extern "C" void JTSPutRHSCache(PreparedGeometry *rhs); -extern "C" void JTSPutLHSCache(PreparedGeometry *lhs); - -extern "C" char JTSisvalid(Geometry *g1); - -/* Converters */ -extern "C" Geometry *PostGIS2JTS_collection(int type, Geometry **geoms, int ngeoms, int SRID, bool is3d); -extern "C" Geometry *PostGIS2JTS_point(const LWPOINT *point); -extern "C" Geometry *PostGIS2JTS_linestring(const LWLINE *line); -extern "C" Geometry *PostGIS2JTS_polygon(const LWPOLY *polygon); - -extern "C" char *JTSasText(Geometry *g1); - -extern "C" char JTSisEmpty(Geometry *g1); -extern "C" char *JTSGeometryType(Geometry *g1); - - -extern "C" char *throw_exception(Geometry *g); - -extern "C" Geometry *JTSIntersection(Geometry *g1,Geometry *g1); -extern "C" Geometry *JTSBuffer(Geometry *g1,double width,int quadsegs); -extern "C" Geometry *JTSConvexHull(Geometry *g1); -extern "C" Geometry *JTSDifference(Geometry *g1,Geometry *g2); -extern "C" Geometry *JTSBoundary(Geometry *g1); -extern "C" Geometry *JTSSymDifference(Geometry *g1,Geometry *g2); -extern "C" Geometry *JTSUnion(Geometry *g1,Geometry *g2); - - -extern "C" POINT3D *JTSGetCoordinate(Geometry *g1); -extern "C" POINT3D *JTSGetCoordinates(Geometry *g1); -extern "C" int JTSGetNumCoordinate(Geometry *g1); -extern "C" Geometry *JTSGetGeometryN(Geometry *g1, int n); -extern "C" Geometry *JTSGetExteriorRing(Geometry *g1); -extern "C" Geometry *JTSGetInteriorRingN(Geometry *g1, int n); -extern "C" int JTSGetNumInteriorRings(Geometry *g1); -extern "C" int JTSGetSRID(Geometry *g1); -extern "C" int JTSGetNumGeometries(Geometry *g1); - -extern "C" char JTSisSimple(Geometry *g1); -extern "C" char JTSequals(Geometry *g1, Geometry*g2); -extern "C" char JTSisRing(Geometry *g1); -extern "C" Geometry *JTSpointonSurface(Geometry *g1); -extern "C" Geometry *JTSGetCentroid(Geometry *g1, int *failure); -extern "C" bool JTSHasZ(Geometry *g1); -extern "C" Geometry * JTSGeometryFromWKT(const char *wkt); - -//########################################################### - -char * StringToChar(String *s); -static GeometryFactory *jtsGeomFactory = NULL; -static noticefunc NOTICE_MESSAGE; - -void -initJTS(noticefunc nf) -{ - if (jtsGeomFactory == NULL) - { - JvCreateJavaVM(NULL); - JvAttachCurrentThread(NULL, NULL); - JvInitClass(&Geometry::class$); - JvInitClass(&GeometryFactory::class$); - JvInitClass(&Coordinate::class$); - JvInitClass(&JTSVersion::class$); - JvInitClass(&PreparedGeometry::class$); - JvInitClass(&PreparedGeometryFactory::class$); - JvInitClass(&PreparedGeometryCache::class$); - - // NOTE: SRID will have to be changed after geometry creation - jtsGeomFactory = new GeometryFactory( new PrecisionModel(), -1); - - } - NOTICE_MESSAGE = nf; -} - - -void -finishJTS(void) -{ - //System::gc(); - JvDetachCurrentThread(); -} - -void -JTSgc(void) -{ - System::gc(); -} - -Geometry * -JTSGeometryFromWKT(const char *wkt) -{ - try { -#ifdef DEBUG_POSTGIS2GEOS - NOTICE_MESSAGE("JTSGeometryFromWKT called"); -#endif - static WKTReader *r = new WKTReader; - jstring wkt_j = JvNewStringLatin1(wkt); - Geometry *g = r->read(wkt_j); - return g; - } catch (Throwable *t) { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return NULL; - } -} - -//----------------------------------------------------------- -// relate()-related functions -// return 0 = false, 1 = true, 2 = error occured -//----------------------------------------------------------- - -char JTSrelateDisjoint(Geometry *g1, Geometry*g2) -{ - try { - bool result; - result = g1->disjoint(g2); - return result; - } - catch (Throwable *t) - { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return 2; - } -} - -char JTSrelateTouches(Geometry *g1, Geometry*g2) -{ - try { - bool result; - result = g1->touches(g2); - return result; - } - catch (Throwable *t) - { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return 2; - } -} - -char JTSrelateIntersects(Geometry *g1, Geometry*g2) -{ - try { - bool result; - result = g1->intersects(g2); - return result; - } - catch (Throwable *t) - { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return 2; - } -} - -char JTSpreparedIntersects(PreparedGeometry *pg, Geometry* g) -{ - try { - bool result; - result = pg->intersects(g); - return result; - } - catch (Throwable *t) - { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return 2; - } -} - -PreparedGeometry *JTSPrepareGeometry(Geometry* g) -{ - try { - PreparedGeometryFactory *pgFact; - PreparedGeometry *pg; - pgFact = new PreparedGeometryFactory(); - pg = pgFact->create(g); - return pg; - } - catch (Throwable *t) - { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return NULL; - } -} - -void JTSPrintPreparedGeometry(PreparedGeometry *pg) -{ - try { - NOTICE_MESSAGE(StringToChar(pg->getGeometry()->toString())); - } - catch (Throwable *t) - { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - } -} - -PreparedGeometry *JTSGetRHSCache() -{ - try { - PreparedGeometryCache *cache; - PreparedGeometry *pg; - cache = PreparedGeometryCache::instance; - pg = cache->getRightHandSide(); - return pg; - } - catch (Throwable *t) - { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return NULL; - } -} - -PreparedGeometry *JTSGetLHSCache() -{ - try { - PreparedGeometryCache *cache; - PreparedGeometry *pg; - cache = PreparedGeometryCache::instance; - pg = cache->getLeftHandSide(); - return pg; - } - catch (Throwable *t) - { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return NULL; - } -} - -void JTSPutRHSCache(PreparedGeometry *rhs) -{ - try { - PreparedGeometryCache *cache; - cache = PreparedGeometryCache::instance; - cache->putRightHandSide(rhs); - } - catch (Throwable *t) - { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - } -} -void JTSPutLHSCache(PreparedGeometry *lhs) -{ - try { - PreparedGeometryCache *cache; - cache = PreparedGeometryCache::instance; - cache->putLeftHandSide(lhs); - } - catch (Throwable *t) - { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - } -} - -char JTSrelateCrosses(Geometry *g1, Geometry*g2) -{ - try { - bool result; - result = g1->crosses(g2); - return result; - } - catch (Throwable *t) - { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return 2; - } -} - -char JTSrelateWithin(Geometry *g1, Geometry*g2) -{ - try { - bool result; - result = g1->within(g2); - return result; - } - catch (Throwable *t) - { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return 2; - } -} - -// call g1->contains(g2) -// returns 0 = false -// 1 = true -// 2 = error was trapped -char JTSrelateContains(Geometry *g1, Geometry*g2) -{ - try { - bool result; - result = g1->contains(g2); - return result; - } - catch (Throwable *t) - { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return 2; - } -} - -char JTSrelateOverlaps(Geometry *g1, Geometry*g2) -{ - try { - bool result; - result = g1->overlaps(g2); - return result; - } - catch (Throwable *t) - { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return 2; - } -} - - -//------------------------------------------------------------------- -// low-level relate functions -//------------------------------------------------------------------ - -char -JTSrelatePattern(Geometry *g1, Geometry*g2,char *pat) -{ - try { - bool result; - string s = pat; - result = g1->relate(g2,JvNewStringLatin1(pat)); - return result; - } - catch (Throwable *t) - { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return 2; - } -} - -char * -JTSrelate(Geometry *g1, Geometry*g2) -{ - - try { - - IntersectionMatrix *im = g1->relate(g2); - - if (im == NULL) return NULL; - - jstring s = im->toString(); - return StringToChar(s); - } - catch (Throwable *t) - { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return NULL; - } -} - - - -//----------------------------------------------------------------- -// isValid -//----------------------------------------------------------------- - - -char JTSisvalid(Geometry *g1) -{ -#if JTS_FIRST_INTERFACE <= 3 && JTS_LAST_INTERFACE >= 3 - IsValidOp ivo(g1); -#endif - bool result; - try { -#if JTS_FIRST_INTERFACE <= 3 && JTS_LAST_INTERFACE >= 3 - result = ivo.isValid(); - if ( result == 0 ) - { - TopologyValidationError *err = ivo.getValidationError(); - if ( err ) { - NOTICE_MESSAGE(StringToChar(err->getMessage())); - } - } -#else // JTS_INTERFACE 3 not supported - result = g1->isValid(); -#endif - return result; - } - catch (Throwable *t) - { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return 2; - } - -} - - -//----------------------------------------------------------------- -// general purpose -//----------------------------------------------------------------- - -char JTSequals(Geometry *g1, Geometry*g2) -{ - try { - bool result; - result = g1->equals(g2); - return result; - } - catch (Throwable *t) - { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return 2; - } -} - - - -char * -JTSasText(Geometry *g1) -{ - try { - NOTICE_MESSAGE("JTSasText called"); - jstring s = g1->toString(); - return StringToChar(s); - } catch (Throwable *t) { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return NULL; - } -} - -char -JTSisEmpty(Geometry *g1) -{ - try { - return g1->isEmpty(); - } catch (Throwable *t) { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return 2; - } -} - -char -JTSisSimple(Geometry *g1) -{ - try { - return g1->isSimple(); - } catch (Throwable *t) { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return 2; - } -} - -char -JTSisRing(Geometry *g1) -{ - try { - return (( (LinearRing*)g1)->isRing()); - } catch (Throwable *t) { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return 2; - } -} - - - -//free the result of this -char * -JTSGeometryType(Geometry *g1) -{ - try { - jstring s = g1->getGeometryType(); - return StringToChar(s); - } catch (Throwable *t) { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return NULL; - } -} - - -//------------------------------------------------------------------- -// JTS functions that return geometries -//------------------------------------------------------------------- - -Geometry * -JTSIntersection(Geometry *g1,Geometry *g2) -{ - try - { - Geometry *g3 = g1->intersection(g2); - return g3; - } catch (Throwable *t) { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return NULL; - } -} - -Geometry * -JTSBuffer(Geometry *g1, double width, int quadrantsegments) -{ - try - { - Geometry *g3 = g1->buffer(width, quadrantsegments); - return g3; - } catch (Throwable *t) { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return NULL; - } -} - -Geometry * -JTSConvexHull(Geometry *g1) -{ - try - { - Geometry *g3 = g1->convexHull(); - return g3; - } catch (Throwable *t) { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return NULL; - } -} - -Geometry * -JTSDifference(Geometry *g1,Geometry *g2) -{ - try { - Geometry *g3 = g1->difference(g2); - return g3; - } catch (Throwable *t) { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return NULL; - } -} - -Geometry * -JTSBoundary(Geometry *g1) -{ - try { - Geometry *g3 = g1->getBoundary(); - return g3; - } catch (Throwable *t) { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return NULL; - } -} - -Geometry * -JTSSymDifference(Geometry *g1,Geometry *g2) -{ - try { - Geometry *g3 = g1->symDifference(g2); - return g3; - } catch (Throwable *t) { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return NULL; - } -} - -Geometry * -JTSUnion(Geometry *g1,Geometry *g2) -{ - try { - Geometry *g3 = g1->union$(g2); - return g3; - } catch (Throwable *t) { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return NULL; - } -} - - -Geometry * -JTSpointonSurface(Geometry *g1) -{ - try { - Geometry *g3 = g1->getInteriorPoint(); - return g3; - } catch (Throwable *t) { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return NULL; - } -} - - - - - -//------------------------------------------------------------------- -// memory management functions -//------------------------------------------------------------------ - - -//BUG:: this leaks memory, but delete kills the PrecisionModel for ALL the geometries -void -JTSdeleteGeometry(Geometry *a) -{ - cerr<<"Don't call JTSdeleteGeometry, the GC will do.."<setSRID(SRID); -} - -void JTSdeleteChar(char *a) -{ - free(a); -} - - -//------------------------------------------------------------------- -//JTS => POSTGIS conversions -//------------------------------------------------------------------- - - -// free the result when done! -// g1 must be a point -POINT3D * -JTSGetCoordinate(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 (Throwable *t) { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return NULL; - } -} - - -//must free the result when done -// result is an array length g1->getNumCoordinates() -POINT3D * -JTSGetCoordinates(Geometry *g1) -{ - try { - int numPoints = g1->getNumPoints(); - POINT3D *result = (POINT3D*)malloc(sizeof(POINT3D)*numPoints); - - JArray *cl = g1->getCoordinates(); - Coordinate **coords = elements(cl); - Coordinate *c; - - for (int t=0; tx; - result[t].y = c->y; - result[t].z = c->z; - } - - return result; - } catch (Throwable *t) { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return NULL; - } - -} - -int -JTSGetNumCoordinate(Geometry *g1) -{ - try{ - return g1->getNumPoints(); - } catch (Throwable *t) { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return 0; - } -} - -int -JTSGetNumInteriorRings(Geometry *g1) -{ - try{ - Polygon *p = (Polygon *) g1; - return p->getNumInteriorRing(); - } catch (Throwable *t) { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return 0; - } -} - - -//only call on GCs (or multi*) -int -JTSGetNumGeometries(Geometry *g1) -{ - try { - GeometryCollection *gc = (GeometryCollection *) g1; - return gc->getNumGeometries(); - } catch (Throwable *t) { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return 0; - } -} - - -//call only on GEOMETRYCOLLECTION or MULTI* -Geometry * -JTSGetGeometryN(Geometry *g1, int n) -{ - try{ - return ((GeometryCollection *)g1)->getGeometryN(n); - } catch (Throwable *t) { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return NULL; - } -} - - -//call only on polygon -Geometry * -JTSGetExteriorRing(Geometry *g1) -{ - try{ - Polygon *p = (Polygon *) g1; - return p->getExteriorRing(); - } catch (Throwable *t) { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return NULL; - } -} - -//call only on polygon -Geometry * -JTSGetInteriorRingN(Geometry *g1,int n) -{ - try { - Polygon *p = (Polygon *) g1; - return p->getInteriorRingN(n); - } catch (Throwable *t) { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return NULL; - } -} - -Geometry * -JTSPolygonize(Geometry **g, unsigned int ngeoms) -{ - NOTICE_MESSAGE("JTS Polygonize unimplemented"); - return NULL; -} - -Geometry * -JTSLineMerge(Geometry *g) -{ - NOTICE_MESSAGE("JTS LineMerge unimplemented"); - return NULL; -} - -Geometry * -JTSGetCentroid(Geometry *g, int *failure) -{ - try{ - Geometry *ret = g->getCentroid(); - *failure = 0; - return ret; - } catch (Throwable *t) { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return NULL; - } -} - -int -JTSGetSRID(Geometry *g1) -{ - try { - return g1->getSRID(); - } catch (Throwable *t) { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return 0; - } -} - -char * -JTSversion() -{ - //char *res = strdup("unknown"); - JTSVersion *v = JTSVersion::CURRENT_VERSION; - if ( ! v ) return "UNDEFINED"; - return StringToChar(v->toString()); - //return res; -} - -bool -JTSHasZ(Geometry *g) -{ - //double az = g->getCoordinate()->z; - //return (finite(az) && az != DoubleNotANumber); - return false; -} - -int -JTSGeometryTypeId(Geometry *g1) -{ - jstring s = g1->getGeometryType(); - char *type = StringToChar(s); - if ( ! strcmp(type, "Point") ) return POINTTYPE; - if ( ! strcmp(type, "Polygon") ) return POLYGONTYPE; - if ( ! strcmp(type, "LineString") ) return LINETYPE; - if ( ! strcmp(type, "LinearRing") ) return LINETYPE; - if ( ! strcmp(type, "MultiLineString") ) return MULTILINETYPE; - if ( ! strcmp(type, "MultiPoint") ) return MULTIPOINTTYPE; - if ( ! strcmp(type, "MultiPolygon") ) return MULTIPOLYGONTYPE; - if ( ! strcmp(type, "GeometryCollection") ) return COLLECTIONTYPE; - else - { - NOTICE_MESSAGE("JTSGeometryTypeId: unknown geometry type: %s", - type); - return -1; // unknown type - } -} - -char * -StringToChar(String *s) -{ - int len = JvGetStringUTFLength(s); - char *result = (char *)malloc(len+1); - JvGetStringUTFRegion(s, 0, len, result); - result[len] = '\0'; - return result; -} - -/* CONVERTERS */ - -Geometry * -PostGIS2JTS_point(const LWPOINT *lwpoint) -{ - POINT3D point; - int SRID; - bool is3d; - -#ifdef DEBUG_POSTGIS2GEOS - char buf[256]; - sprintf(buf, "PostGIS2GEOS_point got lwpoint[%p]", lwpoint); - NOTICE_MESSAGE(buf); -#endif - - if ( lwpoint == NULL ) - { - NOTICE_MESSAGE("PostGIS2GEOS_point got a NULL lwpoint"); - return NULL; - } - - getPoint3dz_p(lwpoint->point, 0, &point); - SRID = lwpoint->SRID; - is3d = TYPE_HASZ(lwpoint->type); - - try - { - Coordinate *c; - - if (is3d) - c = new Coordinate(point.x, point.y, point.z); - else - c = new Coordinate(point.x, point.y); - Geometry *g = jtsGeomFactory->createPoint(c); - if (g==NULL) return NULL; - g->setSRID(SRID); - return g; - } catch (Throwable *t) { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return NULL; - } -} - -/* - * This function must return an all-new allocated object - */ -Geometry * -PostGIS2JTS_linestring(const LWLINE *lwline) -{ - POINTARRAY *pa = lwline->points; - bool is3d = TYPE_HASZ(pa->dims); - int SRID = lwline->SRID; - -#ifdef DEBUG_POSTGIS2GEOS - char buf[256]; - sprintf(buf, "PostGIS2GEOS_line got lwline[%p]", lwline); - NOTICE_MESSAGE(buf); -#endif - - try{ - uint32 t; - JArray*coordlist; - POINT3D p; - - // build Coordinate[] - jobjectArray vc = JvNewObjectArray(pa->npoints, - &Coordinate::class$, NULL); -#ifdef DEBUG_JARRAY - //std::cout<<"PostGIS2JTS_linestring: vc Jarray: "<npoints; t++) - { - getPoint3dz_p(pa, t, &p); - elements(vc)[t] = new Coordinate(p.x, p.y, p.z); - } - } - else //make 2d points - { - for (t=0; tnpoints; t++) - { - getPoint3dz_p(pa, t, &p); - elements(vc)[t] = new Coordinate(p.x, p.y); - } - } - - coordlist = reinterpret_cast*>(vc); - CoordinateSequence *coords = jtsGeomFactory->getCoordinateSequenceFactory()->create(coordlist); - Geometry *g = jtsGeomFactory->createLineString(coords); - if (g==NULL) return NULL; - g->setSRID(SRID); - return g; - } catch (Throwable *t) { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return NULL; - } -} - -Geometry * -PostGIS2JTS_polygon(const LWPOLY *lwpoly) -{ - POINTARRAY *pa; - int SRID = lwpoly->SRID; - bool is3d = TYPE_HASZ(lwpoly->type); - -#ifdef DEBUG_POSTGIS2GEOS - char buf[256]; - sprintf(buf, "PostGIS2GEOS_poly got lwpoly[%p]", lwpoly); - NOTICE_MESSAGE(buf); -#endif - - try - { - //Coordinate *c; - uint32 t; - int ring; - Geometry *g; - LinearRing *outerRing; - LinearRing *innerRing; - CoordinateSequence *cl; - POINT3D p; - - // make outerRing - pa = lwpoly->rings[0]; - jobjectArray vc = JvNewObjectArray(pa->npoints, - &Coordinate::class$, NULL); -#ifdef DEBUG_JARRAY - std::cout<<"PostGIS2JTS_polygon: vc Jarray: "<npoints; t++) - { - getPoint3dz_p(pa, t, &p); - elements(vc)[t] = new Coordinate(p.x,p.y,p.z); - } - } - else - { - for(t=0; tnpoints; t++) - { - getPoint3dz_p(pa, t, &p); - elements(vc)[t] = new Coordinate(p.x,p.y); -#ifdef DEBUG_JARRAY - std::cout<<" elements(vc)["<*coordlist = reinterpret_cast*>(vc); - cl = jtsGeomFactory->getCoordinateSequenceFactory()->create(coordlist); - coordlist=NULL; vc=NULL; - outerRing = jtsGeomFactory->createLinearRing(cl); - cl = NULL; - if (outerRing == NULL) return NULL; - outerRing->setSRID(SRID); - - jobjectArray innerRings = JvNewObjectArray(lwpoly->nrings-1, - &Geometry::class$, NULL); -#ifdef DEBUG_JARRAY - std::cout<<"PostGIS2JTS_polygon: innerRings Jarray: "<nrings; ring++) - { - pa = lwpoly->rings[ring]; - vc = JvNewObjectArray(pa->npoints, - &Coordinate::class$, NULL); - if (is3d) - { - for(t=0; tnpoints; t++) - { - getPoint3dz_p(pa, t, &p); - elements(vc)[t] = new Coordinate(p.x,p.y,p.z); - } - } - else - { - for(t=0; tnpoints; t++) - { - getPoint3dz_p(pa, t, &p); - elements(vc)[t] = new Coordinate(p.x,p.y); - } - } - coordlist = reinterpret_cast*>(vc); - cl = jtsGeomFactory->getCoordinateSequenceFactory()->create(coordlist); - innerRing = (LinearRing *) jtsGeomFactory->createLinearRing(cl); - if (innerRing == NULL) - { - return NULL; - } - innerRing->setSRID(SRID); - elements(innerRings)[ring-1] = innerRing; - } - - JArray*holesList = reinterpret_cast*>(innerRings); - g = jtsGeomFactory->createPolygon(outerRing, holesList); - if (g==NULL) return NULL; - g->setSRID(SRID); - return g; - } catch (Throwable *t) { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return NULL; - } -} - -Geometry * -PostGIS2JTS_collection(int type, Geometry **geoms, int ngeoms, int SRID, bool is3d) -{ -#ifdef DEBUG_POSTGIS2JTS - char buf[256]; - sprintf(buf, "PostGIS2JTS_collection: requested type %d, ngeoms: %d", - type, ngeoms); - NOTICE_MESSAGE(buf); -#endif - - try - { - Geometry *g; - int t; - jobjectArray subGeoms = JvNewObjectArray(ngeoms, - &Geometry::class$, NULL); -#ifdef DEBUG_JARRAY - //std::cout<<"PostGIS2JTS_collection: subGeoms Jarray: "<createGeometryCollection((JArray*)subGeoms); - break; - case MULTIPOINTTYPE: - g = jtsGeomFactory->createMultiPoint((JArray*)subGeoms); - break; - case MULTILINETYPE: - g = jtsGeomFactory->createMultiLineString((JArray*)subGeoms); - break; - case MULTIPOLYGONTYPE: - g = jtsGeomFactory->createMultiPolygon((JArray*)subGeoms); - break; - default: - NOTICE_MESSAGE("Unsupported type request for PostGIS2JTS_collection"); - g = NULL; - - } - if (g==NULL) - return NULL; - g->setSRID(SRID); - return g; - } - catch (Throwable *t) { - NOTICE_MESSAGE(StringToChar(t->getMessage())); - return NULL; - } -} - - diff --git a/lwgeom/lwgeom_nojts.c b/lwgeom/lwgeom_nojts.c deleted file mode 100644 index 8f68905f4..000000000 --- a/lwgeom/lwgeom_nojts.c +++ /dev/null @@ -1,326 +0,0 @@ -#include "postgres.h" -#include "utils/array.h" -#include "utils/builtins.h" -#include "fmgr.h" - -#include "lwgeom_pg.h" -#include "liblwgeom.h" - -Datum postgis_geos_version(PG_FUNCTION_ARGS); -PG_FUNCTION_INFO_V1(postgis_geos_version); -Datum postgis_geos_version(PG_FUNCTION_ARGS) -{ - //elog(ERROR,"JTSversion:: operation not implemented - compile PostGIS with JTS or GEOS support"); - PG_RETURN_NULL(); -} - -Datum postgis_jts_version(PG_FUNCTION_ARGS); -PG_FUNCTION_INFO_V1(postgis_jts_version); -Datum postgis_jts_version(PG_FUNCTION_ARGS) -{ - PG_RETURN_NULL(); -} - -Datum intersection(PG_FUNCTION_ARGS); -PG_FUNCTION_INFO_V1(intersection); -Datum intersection(PG_FUNCTION_ARGS) -{ - elog(ERROR,"intersection:: operation not implemented - compile PostGIS with JTS or GEOS support"); - PG_RETURN_NULL(); // never get here -} - -Datum convexhull(PG_FUNCTION_ARGS); -PG_FUNCTION_INFO_V1(convexhull); -Datum convexhull(PG_FUNCTION_ARGS) -{ - elog(ERROR,"convexhull:: operation not implemented - compile PostGIS with JTS or GEOS support"); - PG_RETURN_NULL(); // never get here -} - -Datum difference(PG_FUNCTION_ARGS); -PG_FUNCTION_INFO_V1(difference); -Datum difference(PG_FUNCTION_ARGS) -{ - elog(ERROR,"difference:: operation not implemented - compile PostGIS with JTS or GEOS support"); - PG_RETURN_NULL(); // never get here -} - -Datum boundary(PG_FUNCTION_ARGS); -PG_FUNCTION_INFO_V1(boundary); -Datum boundary(PG_FUNCTION_ARGS) -{ - elog(ERROR,"boundary:: operation not implemented - compile PostGIS with JTS or GEOS support"); - PG_RETURN_NULL(); // never get here -} - -Datum symdifference(PG_FUNCTION_ARGS); -PG_FUNCTION_INFO_V1(symdifference); -Datum symdifference(PG_FUNCTION_ARGS) -{ - elog(ERROR,"symdifference:: operation not implemented - compile PostGIS with JTS or GEOS support"); - PG_RETURN_NULL(); // never get here -} - -Datum geomunion(PG_FUNCTION_ARGS); -PG_FUNCTION_INFO_V1(geomunion); -Datum geomunion(PG_FUNCTION_ARGS) -{ - elog(ERROR,"geomunion:: operation not implemented - compile PostGIS with JTS or GEOS support"); - PG_RETURN_NULL(); // never get here -} - -Datum buffer(PG_FUNCTION_ARGS); -PG_FUNCTION_INFO_V1(buffer); -Datum buffer(PG_FUNCTION_ARGS) -{ - elog(ERROR,"buffer:: operation not implemented - compile PostGIS with JTS or GEOS support"); - PG_RETURN_NULL(); // never get here -} - -Datum relate_full(PG_FUNCTION_ARGS); -PG_FUNCTION_INFO_V1(relate_full); -Datum relate_full(PG_FUNCTION_ARGS) -{ - elog(ERROR,"relate_full:: operation not implemented - compile PostGIS with JTS or GEOS support"); - PG_RETURN_NULL(); // never get here -} - -Datum relate_pattern(PG_FUNCTION_ARGS); -PG_FUNCTION_INFO_V1(relate_pattern); -Datum relate_pattern(PG_FUNCTION_ARGS) -{ - elog(ERROR,"relate_pattern:: operation not implemented - compile PostGIS with JTS or GEOS support"); - PG_RETURN_NULL(); // never get here -} - -Datum disjoint(PG_FUNCTION_ARGS); -PG_FUNCTION_INFO_V1(disjoint); -Datum disjoint(PG_FUNCTION_ARGS) -{ - elog(ERROR,"disjoint:: operation not implemented - compile PostGIS with JTS or GEOS support"); - PG_RETURN_NULL(); // never get here -} - -Datum intersects(PG_FUNCTION_ARGS); -PG_FUNCTION_INFO_V1(intersects); -Datum intersects(PG_FUNCTION_ARGS) -{ - elog(ERROR,"intersects:: operation not implemented - compile PostGIS with JTS or GEOS support"); - PG_RETURN_NULL(); // never get here -} - -Datum touches(PG_FUNCTION_ARGS); -PG_FUNCTION_INFO_V1(touches); -Datum touches(PG_FUNCTION_ARGS) -{ - elog(ERROR,"touches:: operation not implemented - compile PostGIS with JTS or GEOS support"); - PG_RETURN_NULL(); // never get here -} - -Datum crosses(PG_FUNCTION_ARGS); -PG_FUNCTION_INFO_V1(crosses); -Datum crosses(PG_FUNCTION_ARGS) -{ - elog(ERROR,"crosses:: operation not implemented - compile PostGIS with JTS or GEOS support"); - PG_RETURN_NULL(); // never get here -} - -Datum within(PG_FUNCTION_ARGS); -PG_FUNCTION_INFO_V1(within); -Datum within(PG_FUNCTION_ARGS) -{ - elog(ERROR,"within:: operation not implemented - compile PostGIS with JTS or GEOS support"); - PG_RETURN_NULL(); // never get here -} - -Datum contains(PG_FUNCTION_ARGS); -PG_FUNCTION_INFO_V1(contains); -Datum contains(PG_FUNCTION_ARGS) -{ - elog(ERROR,"contains:: operation not implemented - compile PostGIS with JTS or GEOS support"); - PG_RETURN_NULL(); // never get here -} - -Datum overlaps(PG_FUNCTION_ARGS); -PG_FUNCTION_INFO_V1(overlaps); -Datum overlaps(PG_FUNCTION_ARGS) -{ - elog(ERROR,"overlaps:: operation not implemented - compile PostGIS with JTS or GEOS support"); - PG_RETURN_NULL(); // never get here -} - -Datum isvalid(PG_FUNCTION_ARGS); -PG_FUNCTION_INFO_V1(isvalid); -Datum isvalid(PG_FUNCTION_ARGS) -{ - elog(ERROR,"isvalid:: operation not implemented - compile PostGIS with JTS or GEOS support"); - PG_RETURN_NULL(); // never get here -} - -Datum issimple(PG_FUNCTION_ARGS); -PG_FUNCTION_INFO_V1(issimple); -Datum issimple(PG_FUNCTION_ARGS) -{ - elog(ERROR,"issimple:: operation not implemented - compile PostGIS with JTS or GEOS support"); - PG_RETURN_NULL(); // never get here -} - -Datum geomequals(PG_FUNCTION_ARGS); -PG_FUNCTION_INFO_V1(geomequals); -Datum geomequals(PG_FUNCTION_ARGS) -{ - elog(ERROR,"geomequals:: operation not implemented - compile PostGIS with JTS or GEOS support"); - PG_RETURN_NULL(); // never get here -} - -Datum isring(PG_FUNCTION_ARGS); -PG_FUNCTION_INFO_V1(isring); -Datum isring(PG_FUNCTION_ARGS) -{ - elog(ERROR,"isring:: operation not implemented - compile PostGIS with JTS or GEOS support"); - PG_RETURN_NULL(); // never get here -} - -Datum pointonsurface(PG_FUNCTION_ARGS); -PG_FUNCTION_INFO_V1(pointonsurface); -Datum pointonsurface(PG_FUNCTION_ARGS) -{ - elog(ERROR,"pointonsurface:: operation not implemented - compile PostGIS with JTS or GEOS support"); - PG_RETURN_NULL(); // never get here -} - -Datum unite_garray(PG_FUNCTION_ARGS); -PG_FUNCTION_INFO_V1(unite_garray); -Datum unite_garray(PG_FUNCTION_ARGS) -{ - elog(ERROR,"unite_garray:: operation not implemented - compile PostGIS with JTS or GEOS support"); - PG_RETURN_NULL(); // never get here -} - -Datum polygonize_garray(PG_FUNCTION_ARGS); -PG_FUNCTION_INFO_V1(polygonize_garray); -Datum polygonize_garray(PG_FUNCTION_ARGS) -{ - elog(ERROR,"polygonize_garray:: operation not implemented - compile PostGIS with JTS or GEOS support"); - PG_RETURN_NULL(); // never get here -} - -Datum linemerge(PG_FUNCTION_ARGS); -PG_FUNCTION_INFO_V1(linemerge); -Datum linemerge(PG_FUNCTION_ARGS) -{ - elog(ERROR,"linemerge:: operation not implemented - compile PostGIS with JTS or GEOS support"); - PG_RETURN_NULL(); // never get here -} - -Datum JTSnoop(PG_FUNCTION_ARGS); -PG_FUNCTION_INFO_V1(JTSnoop); -Datum JTSnoop(PG_FUNCTION_ARGS) -{ - elog(ERROR,"JTSnoop:: operation not implemented - compile PostGIS with JTS support"); - PG_RETURN_NULL(); // never get here -} - -Datum GEOSnoop(PG_FUNCTION_ARGS); -PG_FUNCTION_INFO_V1(GEOSnoop); -Datum GEOSnoop(PG_FUNCTION_ARGS) -{ - elog(ERROR,"GEOSnoop:: operation not implemented - compile PostGIS with GEOS support"); - PG_RETURN_NULL(); // never get here -} - -Datum LWGEOM_buildarea(PG_FUNCTION_ARGS); -PG_FUNCTION_INFO_V1(LWGEOM_buildarea); -Datum LWGEOM_buildarea(PG_FUNCTION_ARGS) -{ - elog(ERROR,"BuildArea: operation not implemented - compile PostGIS with JTS or GEOS support"); - PG_RETURN_NULL(); // never get here -} - -LWGEOM *lwgeom_centroid(LWGEOM *in); - -LWGEOM * -lwgeom_centroid(LWGEOM *in) -{ - int type = lwgeom_getType(in->type); - LWPOLY *poly; - LWPOINT *point; - LWMPOLY *mpoly; - POINTARRAY *ring, *pa; - POINT3DZ p, *cent; - int i,j,k; - uint32 num_points_tot = 0; - double tot_x=0, tot_y=0, tot_z=0; - - if (type == POLYGONTYPE) - { - poly = (LWPOLY*)in; - for (j=0; jnrings; j++) - { - ring = poly->rings[j]; - for (k=0; knpoints-1; k++) - { - getPoint3dz_p(ring, k, &p); - tot_x += p.x; - tot_y += p.y; - if ( TYPE_HASZ(ring->dims) ) tot_z += p.z; - } - num_points_tot += ring->npoints-1; - } - } - else if ( type == MULTIPOLYGONTYPE ) - { - mpoly = (LWMPOLY*)in; - for (i=0; ingeoms; i++) - { - poly = mpoly->geoms[i]; - for (j=0; jnrings; j++) - { - ring = poly->rings[j]; - for (k=0; knpoints-1; k++) - { - getPoint3dz_p(ring, k, &p); - tot_x += p.x; - tot_y += p.y; - if ( TYPE_HASZ(ring->dims) ) tot_z += p.z; - } - num_points_tot += ring->npoints-1; - } - } - } - else - { - return NULL; - } - - // Setup point - cent = lwalloc(sizeof(POINT3DZ)); - cent->x = tot_x/num_points_tot; - cent->y = tot_y/num_points_tot; - cent->z = tot_z/num_points_tot; - - // Construct POINTARRAY (paranoia?) - pa = pointArray_construct((uchar *)cent, 1, 0, 1); - - // Construct LWPOINT - point = lwpoint_construct(in->SRID, NULL, pa); - - return (LWGEOM *)point; -} - -Datum centroid(PG_FUNCTION_ARGS); -PG_FUNCTION_INFO_V1(centroid); -Datum centroid(PG_FUNCTION_ARGS) -{ - PG_LWGEOM *geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - LWGEOM *lwgeom = lwgeom_deserialize(SERIALIZED_FORM(geom)); - LWGEOM *centroid = lwgeom_centroid(lwgeom); - PG_LWGEOM *ret; - - lwgeom_release(lwgeom); - if ( ! centroid ) PG_RETURN_NULL(); - ret = pglwgeom_serialize(centroid); - lwgeom_release((LWGEOM *)centroid); - PG_FREE_IF_COPY(geom, 0); - PG_RETURN_POINTER(ret); -} -- 2.50.0