From: Sandro Santilli Date: Wed, 19 Aug 2015 10:52:19 +0000 (+0000) Subject: Add lwgeom_unaryunion to liblwgeom X-Git-Tag: 2.2.0rc1~144 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c50e8ff6f835805e112f3f424f675a227706e937;p=postgis Add lwgeom_unaryunion to liblwgeom Includes postgis change to use liblwgeom version git-svn-id: http://svn.osgeo.org/postgis/trunk@13941 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/NEWS b/NEWS index 201e7fc9d..91210da25 100644 --- a/NEWS +++ b/NEWS @@ -35,6 +35,7 @@ PostGIS 2.2.0 - Topology API in liblwgeom (Sandro Santilli / Regione Toscana - SITA) + - New lwgeom_unaryunion method in liblwgeom - New lwgeom_linemerge method in liblwgeom - New lwgeom_is_simple method in liblwgeom - #3117, Add SFCGAL 1.1 support: add ST_3DDifference, ST_3DUnion, diff --git a/liblwgeom/liblwgeom.h.in b/liblwgeom/liblwgeom.h.in index 16584e610..574fe5cd2 100644 --- a/liblwgeom/liblwgeom.h.in +++ b/liblwgeom/liblwgeom.h.in @@ -2047,6 +2047,7 @@ LWGEOM *lwgeom_difference(const LWGEOM *geom1, const LWGEOM *geom2); LWGEOM *lwgeom_symdifference(const LWGEOM* geom1, const LWGEOM* geom2); LWGEOM *lwgeom_union(const LWGEOM *geom1, const LWGEOM *geom2); LWGEOM *lwgeom_linemerge(const LWGEOM *geom1); +LWGEOM *lwgeom_unaryunion(const LWGEOM *geom1); LWGEOM *lwgeom_clip_by_rect(const LWGEOM *geom1, double x0, double y0, double x1, double y1); LWCOLLECTION *lwgeom_subdivide(const LWGEOM *geom, int maxvertices); diff --git a/liblwgeom/lwgeom_geos.c b/liblwgeom/lwgeom_geos.c index 4394fbb25..dc6052c42 100644 --- a/liblwgeom/lwgeom_geos.c +++ b/liblwgeom/lwgeom_geos.c @@ -679,6 +679,58 @@ lwgeom_linemerge(const LWGEOM *geom1) return result ; } +LWGEOM * +lwgeom_unaryunion(const LWGEOM *geom1) +{ + LWGEOM *result ; + GEOSGeometry *g1, *g3 ; + int is3d = FLAGS_GET_Z(geom1->flags); + int srid = geom1->srid; + + /* Empty.UnaryUnion() == Empty */ + if ( lwgeom_is_empty(geom1) ) + return lwgeom_clone(geom1); + + initGEOS(lwnotice, lwgeom_geos_error); + + g1 = LWGEOM2GEOS(geom1, 0); + if ( 0 == g1 ) /* exception thrown at construction */ + { + lwerror("First argument geometry could not be converted to GEOS: %s", lwgeom_geos_errmsg); + return NULL ; + } + + g3 = GEOSUnaryUnion(g1); + + if (g3 == NULL) + { + GEOSGeom_destroy(g1); + lwerror("Error performing unaryunion: %s", + lwgeom_geos_errmsg); + return NULL; /* never get here */ + } + + LWDEBUGF(3, "result: %s", GEOSGeomToWKT(g3) ) ; + + GEOSSetSRID(g3, srid); + + result = GEOS2LWGEOM(g3, is3d); + + if (result == NULL) + { + GEOSGeom_destroy(g1); + GEOSGeom_destroy(g3); + lwerror("Error performing unaryunion: GEOS2LWGEOM: %s", + lwgeom_geos_errmsg); + return NULL ; /* never get here */ + } + + GEOSGeom_destroy(g1); + GEOSGeom_destroy(g3); + + return result ; +} + LWGEOM * lwgeom_difference(const LWGEOM *geom1, const LWGEOM *geom2) { diff --git a/postgis/lwgeom_geos.c b/postgis/lwgeom_geos.c index 5d473db52..576f91040 100644 --- a/postgis/lwgeom_geos.c +++ b/postgis/lwgeom_geos.c @@ -736,75 +736,24 @@ Datum pgis_union_geometry_array(PG_FUNCTION_ARGS) PG_FUNCTION_INFO_V1(ST_UnaryUnion); Datum ST_UnaryUnion(PG_FUNCTION_ARGS) { -#if POSTGIS_GEOS_VERSION < 33 - PG_RETURN_NULL(); - lwpgerror("The GEOS version this PostGIS binary " - "was compiled against (%d) doesn't support " - "'GEOSUnaryUnion' function (3.3.0+ required)", - POSTGIS_GEOS_VERSION); - PG_RETURN_NULL(); -#else /* POSTGIS_GEOS_VERSION >= 33 */ GSERIALIZED *geom1; - int is3d; - int srid; - GEOSGeometry *g1, *g3; GSERIALIZED *result; - - POSTGIS_DEBUG(2, "in ST_UnaryUnion"); + LWGEOM *lwgeom1, *lwresult ; geom1 = PG_GETARG_GSERIALIZED_P(0); - /* UnaryUnion(empty) == (empty) */ - if ( gserialized_is_empty(geom1) ) - PG_RETURN_POINTER(geom1); - - is3d = ( gserialized_has_z(geom1) ); - - srid = gserialized_get_srid(geom1); - - initGEOS(lwpgnotice, lwgeom_geos_error); - - g1 = (GEOSGeometry *)POSTGIS2GEOS(geom1); - - if ( 0 == g1 ) /* exception thrown at construction */ - { - HANDLE_GEOS_ERROR("First argument geometry could not be converted to GEOS"); - PG_RETURN_NULL(); - } - - POSTGIS_DEBUGF(3, "g1=%s", GEOSGeomToWKT(g1)); - - g3 = GEOSUnaryUnion(g1); - - POSTGIS_DEBUGF(3, "g3=%s", GEOSGeomToWKT(g3)); - GEOSGeom_destroy(g1); - - if (g3 == NULL) - { - HANDLE_GEOS_ERROR("GEOSUnion"); - PG_RETURN_NULL(); /* never get here */ - } - - - GEOSSetSRID(g3, srid); - - result = GEOS2POSTGIS(g3, is3d); - - GEOSGeom_destroy(g3); + lwgeom1 = lwgeom_from_gserialized(geom1) ; - if (result == NULL) - { - elog(ERROR, "ST_UnaryUnion failed converting GEOS result Geometry to PostGIS format"); - PG_RETURN_NULL(); /*never get here */ - } + lwresult = lwgeom_unaryunion(lwgeom1); + result = geometry_serialize(lwresult) ; - /* compressType(result); */ + lwgeom_free(lwgeom1) ; + lwgeom_free(lwresult) ; PG_FREE_IF_COPY(geom1, 0); PG_RETURN_POINTER(result); -#endif /* POSTGIS_GEOS_VERSION >= 33 */ }