From 26e105f295b38355af6f11358e206e5b11548e76 Mon Sep 17 00:00:00 2001 From: strk Date: Fri, 9 Dec 2011 08:46:21 +0000 Subject: [PATCH] Fix CascadedPolygonUnion to discard non-polygonal components created during unioning This is to avoid failures and provide more desirable behaviour. Includes automated testing. Closes ticket #499. git-svn-id: http://svn.osgeo.org/geos/branches/3.3@3532 5242fede-7e19-0410-aef8-94bd7d2200fb --- NEWS | 1 + .../geos/operation/union/CascadedPolygonUnion.h | 30 +++++++++++++++---- src/operation/union/CascadedPolygonUnion.cpp | 34 ++++++++++++++++++++-- tests/xmltester/Makefile.am | 1 + tests/xmltester/tests/general/TestUnaryUnion.xml | 3 +- 5 files changed, 60 insertions(+), 9 deletions(-) diff --git a/NEWS b/NEWS index 88b14003..2260fb0d 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,7 @@ YYYY-MM-DD - Print up to 18 digits of precision for TopologyException points - Fix noding with reduced precision in Buffer operation (#473) - Fix HotPixel original point invalidation (#498) + - Fix CascadedPolygonUnion to discard non-polygonal components (#499) Changes in 3.3.1 2011-09-27 diff --git a/include/geos/operation/union/CascadedPolygonUnion.h b/include/geos/operation/union/CascadedPolygonUnion.h index c893c11c..19326111 100644 --- a/include/geos/operation/union/CascadedPolygonUnion.h +++ b/include/geos/operation/union/CascadedPolygonUnion.h @@ -14,7 +14,7 @@ * ********************************************************************** * - * Last port: operation/union/CascadedPolygonUnion.java r320 (JTS-1.12) + * Last port: operation/union/CascadedPolygonUnion.java r487 (JTS-1.12+) * **********************************************************************/ @@ -25,6 +25,7 @@ #include #include +#include #include "GeometryListHolder.h" @@ -82,6 +83,22 @@ private: */ static int const STRTREE_NODE_CAPACITY = 4; + /** + * Computes a {@link Geometry} containing only {@link Polygonal} components. + * + * Extracts the {@link Polygon}s from the input + * and returns them as an appropriate {@link Polygonal} geometry. + * + * If the input is already Polygonal, it is returned unchanged. + * + * A particular use case is to filter out non-polygonal components + * returned from an overlay operation. + * + * @param g the geometry to filter + * @return a Polygonal geometry + */ + static std::auto_ptr restrictToPolygons(std::auto_ptr g); + public: CascadedPolygonUnion(); @@ -155,9 +172,9 @@ private: * Unions a section of a list using a recursive binary union on each half * of the section. * - * @param geoms - * @param start - * @param end + * @param geoms the list of geometries containing the section to union + * @param start the start index of the section + * @param end the index after the end of the section * @return the union of the list section */ geom::Geometry* binaryUnion(GeometryListHolder* geoms, std::size_t start, @@ -186,7 +203,10 @@ private: geom::Geometry* unionOptimized(geom::Geometry* g0, geom::Geometry* g1); /** - * Unions two polygonal geometries. + * \brief + * Unions two polygonal geometries, restricting computation + * to the envelope intersection where possible. + * * The case of MultiPolygons is optimized to union only * the polygons which lie in the intersection of the two geometry's * envelopes. diff --git a/src/operation/union/CascadedPolygonUnion.cpp b/src/operation/union/CascadedPolygonUnion.cpp index 1356cae6..df1e0fc7 100644 --- a/src/operation/union/CascadedPolygonUnion.cpp +++ b/src/operation/union/CascadedPolygonUnion.cpp @@ -14,7 +14,7 @@ * ********************************************************************** * - * Last port: operation/union/CascadedPolygonUnion.java r320 (JTS-1.12) + * Last port: operation/union/CascadedPolygonUnion.java r487 (JTS-1.12+) * **********************************************************************/ @@ -24,6 +24,7 @@ #include #include #include +#include #include // std #include @@ -212,7 +213,36 @@ CascadedPolygonUnion::extractByEnvelope(geom::Envelope const& env, geom::Geometry* CascadedPolygonUnion::unionActual(geom::Geometry* g0, geom::Geometry* g1) { - return g0->Union(g1); + return restrictToPolygons(std::auto_ptr(g0->Union(g1))).release(); +} + +std::auto_ptr +CascadedPolygonUnion::restrictToPolygons(std::auto_ptr g) +{ + using namespace geom; + using namespace std; + + if ( dynamic_cast(g.get()) ) { + return g; + } + + Polygon::ConstVect polygons; + util::PolygonExtracter::getPolygons(*g, polygons); + + if (polygons.size() == 1) + return std::auto_ptr(polygons[0]->clone()); + + typedef vector GeomVect; + + Polygon::ConstVect::size_type n = polygons.size(); + GeomVect* newpolys = new GeomVect(n); + for (Polygon::ConstVect::size_type i=0; iclone(); + } + return auto_ptr( + g->getFactory()->createMultiPolygon(newpolys) + ); + } } // namespace geos.operation.union diff --git a/tests/xmltester/Makefile.am b/tests/xmltester/Makefile.am index bc5dbe3a..63e05c43 100644 --- a/tests/xmltester/Makefile.am +++ b/tests/xmltester/Makefile.am @@ -62,6 +62,7 @@ SAFE_XMLTESTS=$(srcdir)/tests/testLeaksBig.xml \ $(srcdir)/tests/general/TestRelatePP.xml \ $(srcdir)/tests/general/TestSimple.xml \ $(srcdir)/tests/general/TestUnaryUnion.xml \ + $(srcdir)/tests/general/TestUnaryUnionFloating.xml \ $(srcdir)/tests/general/TestValid.xml \ $(srcdir)/tests/general/TestValid2.xml \ $(srcdir)/tests/general/TestValid2-big.xml \ diff --git a/tests/xmltester/tests/general/TestUnaryUnion.xml b/tests/xmltester/tests/general/TestUnaryUnion.xml index 7555a152..57344a4f 100644 --- a/tests/xmltester/tests/general/TestUnaryUnion.xml +++ b/tests/xmltester/tests/general/TestUnaryUnion.xml @@ -151,8 +151,7 @@ - GEOMETRYCOLLECTION (LINESTRING (0 0, 20 0), - POLYGON ((150 0, 20 0, 20 100, 180 100, 180 0, 150 0))) + POLYGON ((150 0, 20 0, 20 100, 180 100, 180 0, 150 0)) -- 2.11.4.GIT