EVOLUTION-MANAGER
Edit File: UnaryUnionOp.cpp
/********************************************************************** * * GEOS - Geometry Engine Open Source * http://geos.osgeo.org * * Copyright (C) 2011 Sandro Santilli <strk@kbt.io * * This is free software; you can redistribute and/or modify it under * the terms of the GNU Lesser General Public Licence as published * by the Free Software Foundation. * See the COPYING file for more information. * ********************************************************************** * * Last port: operation/union/UnaryUnionOp.java r320 (JTS-1.12) * **********************************************************************/ #include <memory> // for unique_ptr #include <cassert> // for assert #include <algorithm> // for copy #include <geos/operation/union/UnaryUnionOp.h> #include <geos/operation/union/CascadedUnion.h> #include <geos/operation/union/CascadedPolygonUnion.h> #include <geos/operation/union/PointGeometryUnion.h> #include <geos/geom/Coordinate.h> #include <geos/geom/Point.h> #include <geos/geom/MultiPoint.h> #include <geos/geom/MultiLineString.h> #include <geos/geom/MultiPolygon.h> #include <geos/geom/GeometryCollection.h> #include <geos/geom/Geometry.h> #include <geos/geom/Location.h> #include <geos/geom/GeometryFactory.h> #include <geos/geom/util/GeometryCombiner.h> #include <geos/algorithm/PointLocator.h> namespace geos { namespace operation { // geos::operation namespace geounion { // geos::operation::geounion /*private*/ std::unique_ptr<geom::Geometry> UnaryUnionOp::unionWithNull(std::unique_ptr<geom::Geometry> g0, std::unique_ptr<geom::Geometry> g1) { std::unique_ptr<geom::Geometry> ret; if((! g0.get()) && (! g1.get())) { return ret; } if(! g0.get()) { return g1; } if(! g1.get()) { return g0; } ret = g0->Union(g1.get()); return ret; } /*public*/ std::unique_ptr<geom::Geometry> UnaryUnionOp::Union() { typedef std::unique_ptr<geom::Geometry> GeomPtr; GeomPtr ret; if(! geomFact) { return ret; } /** * For points and lines, only a single union operation is * required, since the OGC model allowings self-intersecting * MultiPoint and MultiLineStrings. * This is not the case for polygons, so Cascaded Union is required. */ GeomPtr unionPoints; if(!points.empty()) { GeomPtr ptGeom = geomFact->buildGeometry(points.begin(), points.end()); unionPoints = unionNoOpt(*ptGeom); } GeomPtr unionLines; if(!lines.empty()) { /* JTS compatibility NOTE: * we use cascaded here for robustness [1] * but also add a final unionNoOpt step to deal with * self-intersecting lines [2] * * [1](http://trac.osgeo.org/geos/ticket/392 * [2](http://trac.osgeo.org/geos/ticket/482 * */ try { auto combinedLines = geomFact->buildGeometry(lines.begin(), lines.end()); unionLines = unionNoOpt(*combinedLines); } catch (geos::util::TopologyException &) { unionLines.reset(CascadedUnion::Union(lines.begin(), lines.end())); if(unionLines.get()) { unionLines = unionNoOpt(*unionLines); } } } GeomPtr unionPolygons; if(!polygons.empty()) { unionPolygons.reset(CascadedPolygonUnion::Union(polygons.begin(), polygons.end())); } /** * Performing two unions is somewhat inefficient, * but is mitigated by unioning lines and points first */ GeomPtr unionLA = unionWithNull(std::move(unionLines), std::move(unionPolygons)); assert(!unionLines.get()); assert(!unionPolygons.get()); if(! unionPoints.get()) { ret = std::move(unionLA); assert(!unionLA.get()); } else if(! unionLA.get()) { ret = std::move(unionPoints); assert(!unionPoints.get()); } else { ret = PointGeometryUnion::Union(*unionPoints, *unionLA); } if(! ret.get()) { ret = geomFact->createGeometryCollection(); } return ret; } } // namespace geos::operation::union } // namespace geos::operation } // namespace geos