]> granicus.if.org Git - postgis/commitdiff
Add GEOMETRYCOLLECTION input support for ST_MakeValid (#1719)
authorSandro Santilli <strk@keybit.net>
Tue, 12 Jun 2012 09:09:06 +0000 (09:09 +0000)
committerSandro Santilli <strk@keybit.net>
Tue, 12 Jun 2012 09:09:06 +0000 (09:09 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@9892 b70326c6-7e19-0410-871a-916f4a2858ee

NEWS
liblwgeom/cunit/cu_clean.c
liblwgeom/lwgeom_geos_clean.c

diff --git a/NEWS b/NEWS
index 8d05901aa303b8c03c0f76c510f9ae2754e54410..2b637dd343d73c5fedd43997c4d5f3b95cdb75a3 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,7 @@ PostGIS 2.1.0
   - ST_Raster2WorldCoord, ST_World2RasterCoord (Bborie Park / UC Davis)
   - Tiger Geocoder - Tiger 2011 loader (Regina Obe / Paragon Corporation) 
     Funded by Hunter Systems Group
+  - GEOMETRYCOLLECTION support for ST_MakeValid (Sandro Santilli / Vizzuality)
 
 * Enhancements *
 
index 367659509ae62d47993ddb3c97f6cf8371b5a396..be771db8c40df5af2d81ca521db66b954b8c5ca4 100644 (file)
@@ -21,6 +21,7 @@ static void test_lwgeom_make_valid(void)
 #if POSTGIS_GEOS_VERSION >= 33
        LWGEOM *gin, *gout;
        int ret;
+       char *ewkt;
 
        /* Because i don't trust that much prior tests...  ;) */
        cu_error_msg_reset();
@@ -42,6 +43,24 @@ static void test_lwgeom_make_valid(void)
        lwgeom_free(gout);
        lwgeom_free(gin);
 
+
+       gin = lwgeom_from_wkt(
+"GEOMETRYCOLLECTION(LINESTRING(0 0, 0 0), POLYGON((0 0, 10 10, 10 0, 0 10, 0 0)), LINESTRING(10 0, 10 10))",
+               LW_PARSER_CHECK_NONE);
+       CU_ASSERT(gin);
+
+       gout = lwgeom_make_valid(gin);
+       CU_ASSERT(gout);
+
+       ewkt = lwgeom_to_ewkt(gout);
+       printf("c = %s\n", ewkt);
+       CU_ASSERT_STRING_EQUAL(ewkt,
+"GEOMETRYCOLLECTION(POINT(0 0),MULTIPOLYGON(((5 5,0 0,0 10,5 5)),((5 5,10 10,10 0,5 5))),LINESTRING(10 0,10 10))");
+       lwfree(ewkt);
+
+       lwgeom_free(gout);
+       lwgeom_free(gin);
+
 #endif /* POSTGIS_GEOS_VERSION >= 33 */
 }
 
index 887fc745ce9cf436514f1c6cbe13ccc524459d1c..f0ec20faab068b83904c1bcdc59fcbfefd28d01d 100644 (file)
@@ -613,6 +613,7 @@ LWGEOM_GEOS_makeValidPolygon(const GEOSGeometry* gin)
                        /* cleanup and throw */
                        GEOSGeom_destroy(geos_cut_edges);
                        GEOSGeom_destroy(geos_area);
+                       /* TODO: Shouldn't this be an lwerror ? */
                        lwnotice("GEOSDifference() threw an error: %s",
                                 lwgeom_geos_errmsg);
                        return NULL;
@@ -664,6 +665,7 @@ LWGEOM_GEOS_makeValidPolygon(const GEOSGeometry* gin)
                if ( ! gout )   /* an exception again */
                {
                        /* cleanup and throw */
+                       /* TODO: Shouldn't this be an lwerror ? */
                        lwnotice("GEOSGeom_createCollection() threw an error: %s",
                                 lwgeom_geos_errmsg);
                        /* TODO: cleanup! */
@@ -792,6 +794,58 @@ LWGEOM_GEOS_makeValidMultiLine(const GEOSGeometry* gin)
        return gout;
 }
 
+static GEOSGeometry* LWGEOM_GEOS_makeValid(const GEOSGeometry*);
+
+/*
+ * We expect initGEOS being called already.
+ * Will return NULL on error (expect error handler being called by then)
+ */
+static GEOSGeometry*
+LWGEOM_GEOS_makeValidCollection(const GEOSGeometry* gin)
+{
+       int nvgeoms;
+       GEOSGeometry **vgeoms;
+       GEOSGeom gout;
+       unsigned int i;
+
+       nvgeoms = GEOSGetNumGeometries(gin);
+       if ( nvgeoms == -1 ) {
+               lwerror("GEOSGetNumGeometries: %s", lwgeom_geos_errmsg);
+               return 0;
+       }
+
+       vgeoms = lwalloc( sizeof(GEOSGeometry*) * nvgeoms );
+       if ( ! vgeoms ) {
+               lwerror("LWGEOM_GEOS_makeValidCollection: out of memory");
+               return 0;
+       }
+
+       for ( i=0; i<nvgeoms; ++i ) {
+               vgeoms[i] = LWGEOM_GEOS_makeValid( GEOSGetGeometryN(gin, i) );
+               if ( ! vgeoms[i] ) {
+                       while (i--) GEOSGeom_destroy(vgeoms[i]);
+                       lwfree(vgeoms);
+                       /* we expect lwerror being called already by makeValid */
+                       return NULL;
+               }
+       }
+
+       /* Collect areas and lines (if any line) */
+       gout = GEOSGeom_createCollection(GEOS_GEOMETRYCOLLECTION, vgeoms, nvgeoms);
+       lwfree(vgeoms);
+       if ( ! gout )   /* an exception again */
+       {
+               /* cleanup and throw */
+               for ( i=0; i<nvgeoms; ++i ) GEOSGeom_destroy(vgeoms[i]);
+               lwerror("GEOSGeom_createCollection() threw an error: %s",
+                        lwgeom_geos_errmsg);
+               return NULL;
+       }
+
+       return gout;
+
+}
+
 
 static GEOSGeometry*
 LWGEOM_GEOS_makeValid(const GEOSGeometry* gin)
@@ -873,6 +927,18 @@ LWGEOM_GEOS_makeValid(const GEOSGeometry* gin)
                break; /* we've done */
        }
 
+       case GEOS_GEOMETRYCOLLECTION:
+       {
+               gout = LWGEOM_GEOS_makeValidCollection(gin);
+               if ( ! gout )  /* an exception or something */
+               {
+                       /* cleanup and throw */
+                       lwerror("%s", lwgeom_geos_errmsg);
+                       return NULL;
+               }
+               break; /* we've done */
+       }
+
        default:
        {
                char* typname = GEOSGeomType(gin);