]> granicus.if.org Git - postgis/commitdiff
ST_UnaryUnion and test
authorSandro Santilli <strk@keybit.net>
Mon, 14 Feb 2011 17:26:38 +0000 (17:26 +0000)
committerSandro Santilli <strk@keybit.net>
Mon, 14 Feb 2011 17:26:38 +0000 (17:26 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@6816 b70326c6-7e19-0410-871a-916f4a2858ee

postgis/lwgeom_geos.c
postgis/postgis.sql.in.c
regress/Makefile.in
regress/unaryunion.sql [new file with mode: 0644]
regress/unaryunion_expected [new file with mode: 0644]

index 1b71b74abb0299f2ed9a2112d879db2c8baffe5f..a208e770b695d3f87666f9accfe8191aa04502ee 100644 (file)
@@ -4,7 +4,7 @@
  * PostGIS - Spatial Types for PostgreSQL
  * http://postgis.refractions.net
  *
- * Copyright 2009-2010 Sandro Santilli <strk@keybit.net>
+ * Copyright 2009-2011 Sandro Santilli <strk@keybit.net>
  * Copyright 2008 Paul Ramsey <pramsey@cleverelephant.ca>
  * Copyright 2001-2003 Refractions Research Inc.
  *
@@ -52,6 +52,7 @@ Datum difference(PG_FUNCTION_ARGS);
 Datum boundary(PG_FUNCTION_ARGS);
 Datum symdifference(PG_FUNCTION_ARGS);
 Datum geomunion(PG_FUNCTION_ARGS);
+Datum ST_UnaryUnion(PG_FUNCTION_ARGS);
 Datum issimple(PG_FUNCTION_ARGS);
 Datum isring(PG_FUNCTION_ARGS);
 Datum geomequals(PG_FUNCTION_ARGS);
@@ -671,6 +672,96 @@ Datum pgis_union_geometry_array(PG_FUNCTION_ARGS)
 
 }
 
+/**
+ * @example ST_UnaryUnion {@link #geomunion} SELECT ST_UnaryUnion(
+ *      'POLYGON((0 0, 10 0, 0 10, 10 10, 0 0))'
+ * );
+ *
+ */
+PG_FUNCTION_INFO_V1(ST_UnaryUnion);
+Datum ST_UnaryUnion(PG_FUNCTION_ARGS)
+{
+#if POSTGIS_GEOS_VERSION < 33
+       PG_RETURN_NULL();
+       lwerror("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 */
+       PG_LWGEOM *geom1;
+       int is3d;
+       int srid;
+       GEOSGeometry *g1, *g3;
+       PG_LWGEOM *result;
+
+       POSTGIS_DEBUG(2, "in ST_UnaryUnion");
+
+       PROFSTART(PROF_QRUN);
+
+       geom1 = (PG_LWGEOM *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+
+       /* UnaryUnion(empty) == (empty) */
+       if ( pglwgeom_is_empty(geom1) )
+               PG_RETURN_POINTER(geom1);
+
+       is3d = ( pglwgeom_has_z(geom1) );
+
+       srid = pglwgeom_get_srid(geom1);
+
+       initGEOS(lwnotice, lwgeom_geos_error);
+
+       PROFSTART(PROF_P2G1);
+       g1 = (GEOSGeometry *)POSTGIS2GEOS(geom1);
+       PROFSTOP(PROF_P2G1);
+       if ( 0 == g1 )   /* exception thrown at construction */
+       {
+               lwerror("First argument geometry could not be converted to GEOS: %s", lwgeom_geos_errmsg);
+               PG_RETURN_NULL();
+       }
+
+       POSTGIS_DEBUGF(3, "g1=%s", GEOSGeomToWKT(g1));
+
+       PROFSTART(PROF_GRUN);
+       g3 = GEOSUnaryUnion(g1);
+       PROFSTOP(PROF_GRUN);
+
+       POSTGIS_DEBUGF(3, "g3=%s", GEOSGeomToWKT(g3));
+
+       GEOSGeom_destroy(g1);
+
+       if (g3 == NULL)
+       {
+               lwerror("GEOSUnion: %s", lwgeom_geos_errmsg);
+               PG_RETURN_NULL(); /* never get here */
+       }
+
+
+       GEOSSetSRID(g3, srid);
+
+       PROFSTART(PROF_G2P);
+       result = GEOS2POSTGIS(g3, is3d);
+       PROFSTOP(PROF_G2P);
+
+       GEOSGeom_destroy(g3);
+
+       if (result == NULL)
+       {
+               elog(ERROR, "ST_UnaryUnion failed converting GEOS result Geometry to PostGIS format");
+               PG_RETURN_NULL(); /*never get here */
+       }
+
+       /* compressType(result); */
+
+       PROFSTOP(PROF_QRUN);
+       PROFREPORT("geos",geom1, NULL, result);
+
+       PG_FREE_IF_COPY(geom1, 0);
+
+       PG_RETURN_POINTER(result);
+#endif /* POSTGIS_GEOS_VERSION >= 33 */
+}
+
 
 /**
  * @example geomunion {@link #geomunion} SELECT geomunion(
index 56e4cdae9a4c8ead39c749f47a97e0712292b35a..83624dd156aafa1edb11e63bf8bef9097416a3f8 100644 (file)
@@ -2987,6 +2987,13 @@ CREATE OR REPLACE FUNCTION ST_Union(geometry,geometry)
        AS 'MODULE_PATHNAME','geomunion'
        LANGUAGE 'C' IMMUTABLE STRICT;
 
+-- Availability: 2.0.0
+-- Requires: GEOS-3.3.0
+CREATE OR REPLACE FUNCTION ST_UnaryUnion(geometry)
+       RETURNS geometry
+       AS 'MODULE_PATHNAME','ST_UnaryUnion'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
 -- ST_RemoveRepeatedPoints(in geometry)
 --
 -- Removes duplicate vertices in input.
index 9ff2afec0a353a1f71441e4cf0085d3e86deda5e..3d293a4ee2a227b43ec721d1e129d197292726a0 100644 (file)
@@ -106,6 +106,11 @@ ifeq ($(shell expr $(POSTGIS_GEOS_VERSION) ">=" 33),1)
        TESTS += snap
 endif
 
+# ST_UnaryUnion if GEOS >= 3.3
+ifeq ($(shell expr $(POSTGIS_GEOS_VERSION) ">=" 33),1)
+       TESTS += unaryunion
+endif
+
 all install uninstall distclean:
 
 postgis.sql: ../postgis/postgis.sql
diff --git a/regress/unaryunion.sql b/regress/unaryunion.sql
new file mode 100644 (file)
index 0000000..7882673
--- /dev/null
@@ -0,0 +1,10 @@
+
+-- Noding a multilinestring
+SELECT 1, ST_AsText(ST_UnaryUnion('MULTILINESTRING((0 0, 10 0), (5 -5, 5 5))'));
+
+-- Unioning a set of polygons (CascadedUnion)
+SELECT 2, ST_AsText(ST_UnaryUnion('GEOMETRYCOLLECTION(POLYGON((0 0, 10 0, 10 10, 0 10, 0 0)),POLYGON((5 5, 15 5, 15 15, 5 15, 5 5)))'));
+
+-- Unioning an heterogeneous collection of geometries
+SELECT 3, ST_AsText(ST_UnaryUnion('GEOMETRYCOLLECTION(POLYGON((0 0, 10 0, 10 10, 0 10, 0 0)),POLYGON((5 5, 15 5, 15 15, 5 15, 5 5)), MULTIPOINT(5 4, -5 4),LINESTRING(2 -10, 2 20))'));
+
diff --git a/regress/unaryunion_expected b/regress/unaryunion_expected
new file mode 100644 (file)
index 0000000..074bc6c
--- /dev/null
@@ -0,0 +1,3 @@
+1|MULTILINESTRING((0 0,5 0),(5 0,10 0),(5 -5,5 0),(5 0,5 5))
+2|POLYGON((10 5,10 0,0 0,0 10,5 10,5 15,15 15,15 5,10 5))
+3|GEOMETRYCOLLECTION(POINT(-5 4),LINESTRING(2 -10,2 0),LINESTRING(2 10,2 20),POLYGON((10 5,10 0,2 0,0 0,0 10,2 10,5 10,5 15,15 15,15 5,10 5)))