From c3b55ae2a95f4838ddc5f94175f48fe1d2cdcc5c Mon Sep 17 00:00:00 2001 From: Sandro Santilli Date: Thu, 11 Feb 2010 18:56:06 +0000 Subject: [PATCH] Separate GEOS part of 'buildarea' function from POSTGIS part of it (might eventually be moved down to GEOS) [RT-SIGTA] git-svn-id: http://svn.osgeo.org/postgis/trunk@5229 b70326c6-7e19-0410-871a-916f4a2858ee --- postgis/lwgeom_geos.c | 215 +++++++++++++++++++++++------------------- postgis/lwgeom_geos.h | 2 +- 2 files changed, 120 insertions(+), 97 deletions(-) diff --git a/postgis/lwgeom_geos.c b/postgis/lwgeom_geos.c index 07151fa2a..95384ebe8 100644 --- a/postgis/lwgeom_geos.c +++ b/postgis/lwgeom_geos.c @@ -102,6 +102,111 @@ errorlogger(const char *fmt, ...) } +/* + * This function would better be moved to the GEOS C-API, + * but isn't available up to 3.2.0 + */ +GEOSGeometry* LWGEOM_GEOS_buildArea(const GEOSGeometry* geom_in); +GEOSGeometry* +LWGEOM_GEOS_buildArea(const GEOSGeometry* geom_in) +{ + GEOSGeometry *tmp; + GEOSGeometry *geos_result, *shp; + GEOSGeometry const *vgeoms[1]; + unsigned int i, ngeoms; + + vgeoms[0] = geom_in; + geos_result = GEOSPolygonize(vgeoms, 1); + + POSTGIS_DEBUGF(3, "GEOSpolygonize returned @ %p", geos_result); + + /* Null return from GEOSpolygonize (an exception) */ + if ( ! geos_result ) return 0; + + /* + * We should now have a collection + */ +#if PARANOIA_LEVEL > 0 + if ( GEOSGeometryTypeId(geos_result) != COLLECTIONTYPE ) + { + GEOSGeom_destroy(geos_result); + lwerror("Unexpected return from GEOSpolygonize"); + return 0; + } +#endif + + ngeoms = GEOSGetNumGeometries(geos_result); + + POSTGIS_DEBUGF(3, "GEOSpolygonize: ngeoms in polygonize output: %d", ngeoms); + + /* + * No geometries in collection, early out + */ + if ( ngeoms == 0 ) + { + return geos_result; + } + + /* + * Return first geometry if we only have one in collection, + * to avoid the unnecessary Geometry clone below. + */ + if ( ngeoms == 1 ) + { + tmp = (GEOSGeometry *)GEOSGetGeometryN(geos_result, 0); + if ( ! tmp ) return 0; /* exception */ + shp = GEOSGeom_clone(tmp); + GEOSGeom_destroy(geos_result); /* only safe after the clone above */ + return shp; + } + + /* + * Iteratively invoke symdifference on outer rings + * as suggested by Carl Anderson: + * postgis-devel/2005-December/001805.html + */ + shp = NULL; + for (i=0; i= 3 static int call=1; @@ -3395,105 +3498,25 @@ Datum LWGEOM_buildarea(PG_FUNCTION_ARGS) initGEOS(lwnotice, lwerror); - vgeoms[0] = (const GEOSGeometry *)POSTGIS2GEOS(geom); - geos_result = GEOSPolygonize(vgeoms, 1); - GEOSGeom_destroy((GEOSGeometry *)vgeoms[0]); - - POSTGIS_DEBUGF(3, "GEOSpolygonize returned @ %p", geos_result); - - /* Null return from GEOSpolygonize */ - if ( ! geos_result ) PG_RETURN_NULL(); + geos_in = POSTGIS2GEOS(geom); + geos_out = LWGEOM_GEOS_buildArea(geos_in); + GEOSGeom_destroy(geos_in); - /* - * We should now have a collection - */ -#if PARANOIA_LEVEL > 0 - if ( GEOSGeometryTypeId(geos_result) != COLLECTIONTYPE ) + if ( ! geos_out ) /* exception thrown.. */ { - GEOSGeom_destroy(geos_result); - lwerror("Unexpected return from GEOSpolygonize"); PG_RETURN_NULL(); } -#endif - - ngeoms = GEOSGetNumGeometries(geos_result); - POSTGIS_DEBUGF(3, "GEOSpolygonize: ngeoms in polygonize output: %d", ngeoms); - - /* - * No geometries in collection, return NULL - */ - if ( ngeoms == 0 ) + /* If no geometries are in result collection, return NULL */ + if ( GEOSGetNumGeometries(geos_out) == 0 ) { - GEOSGeom_destroy(geos_result); + GEOSGeom_destroy(geos_out); PG_RETURN_NULL(); } - /* - * Return first geometry if we only have one in collection, - * to avoid the unnecessary Geometry clone below. - */ - if ( ngeoms == 1 ) - { - shp = (GEOSGeometry *)GEOSGetGeometryN(geos_result, 0); - lwg = GEOS2LWGEOM(shp, is3d); - lwg->SRID = SRID; - result = pglwgeom_serialize(lwg); - lwgeom_release(lwg); - GEOSGeom_destroy(geos_result); - PG_RETURN_POINTER(result); - } - - /* - * Iteratively invoke symdifference on outer rings - * as suggested by Carl Anderson: - * postgis-devel/2005-December/001805.html - */ - shp = NULL; - for (i=0; i 0 if ( result == NULL ) diff --git a/postgis/lwgeom_geos.h b/postgis/lwgeom_geos.h index 5e3377621..deb559336 100644 --- a/postgis/lwgeom_geos.h +++ b/postgis/lwgeom_geos.h @@ -43,7 +43,7 @@ */ PG_LWGEOM *GEOS2POSTGIS(GEOSGeom geom, char want3d); -const GEOSGeometry * POSTGIS2GEOS(PG_LWGEOM *g); +GEOSGeometry * POSTGIS2GEOS(PG_LWGEOM *g); LWGEOM *GEOS2LWGEOM(const GEOSGeometry *geom, char want3d); GEOSGeometry * LWGEOM2GEOS(LWGEOM *g); -- 2.50.1