[geos-commits] [SCM] GEOS branch main updated. 4fb859518f4642a0ac8b0f967d1dd54d2a2a7f02
git at osgeo.org
git at osgeo.org
Thu Jul 9 11:18:48 PDT 2026
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GEOS".
The branch, main has been updated
via 4fb859518f4642a0ac8b0f967d1dd54d2a2a7f02 (commit)
from b50bb516081b9c3193fbc8001c08493d275f8fa2 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 4fb859518f4642a0ac8b0f967d1dd54d2a2a7f02
Author: Daniel Baston <dbaston at gmail.com>
Date: Thu Jul 9 14:18:30 2026 -0400
UnaryUnionOp: support curved geometries (#1468)
diff --git a/capi/geos_ts_c.cpp b/capi/geos_ts_c.cpp
index f95c294df..ee6391ca2 100644
--- a/capi/geos_ts_c.cpp
+++ b/capi/geos_ts_c.cpp
@@ -2077,9 +2077,10 @@ extern "C" {
Geometry*
GEOSUnaryUnion_r(GEOSContextHandle_t extHandle, const Geometry* g)
{
- return convertCurvesAndExecute<Interruptible, ReportsProgress>(extHandle, g, [&](const Geometry* input1) {
- return geos::operation::geounion::UnaryUnionOp::Union(*input1, &extHandle->progressFunction);
- return input1->Union();
+ return execute<Interruptible, ReportsProgress>(extHandle, [&]() {
+ auto g3 = geos::operation::geounion::UnaryUnionOp::Union(*g, &extHandle->progressFunction);
+ g3->setSRID(g->getSRID());
+ return g3.release();
});
}
diff --git a/include/geos/operation/union/CascadedPolygonUnion.h b/include/geos/operation/union/CascadedPolygonUnion.h
index fcc5ba9a7..710a56ac4 100644
--- a/include/geos/operation/union/CascadedPolygonUnion.h
+++ b/include/geos/operation/union/CascadedPolygonUnion.h
@@ -32,7 +32,7 @@ namespace geos {
namespace geom {
class GeometryFactory;
class Geometry;
-class Polygon;
+class Surface;
class MultiPolygon;
class Envelope;
}
@@ -103,7 +103,7 @@ private:
*/
class GEOS_DLL CascadedPolygonUnion {
private:
- std::vector<geom::Polygon*>* inputPolys;
+ const std::vector<const geom::Surface*>& inputPolys;
geom::GeometryFactory const* geomFactory;
/**
@@ -116,23 +116,23 @@ private:
static int const STRTREE_NODE_CAPACITY = 4;
/** \brief
- * Computes a [Geometry](@ref geom::Geometry) containing only polygonal components.
+ * Computes a [Geometry](@ref geom::Geometry) containing only
+ * surface components (dimension == 2).
*
- * Extracts the [Polygons](@ref geom::Polygon) from the input
+ * Extracts the [Surfaces](@ref geom::Surface) from the input
* and returns them as an appropriate polygonal geometry.
*
- * If the input is already `Polygonal`, it is returned unchanged.
+ * If the input is already a surface, it is returned unchanged.
*
- * A particular use case is to filter out non-polygonal components
+ * A particular use case is to filter out non-surface components
* returned from an overlay operation.
*
* @param g the geometry to filter
- * @return a Polygonal geometry
+ * @return a Surface geometry
*/
- static std::unique_ptr<geom::Geometry> restrictToPolygons(std::unique_ptr<geom::Geometry> g);
+ static std::unique_ptr<geom::Geometry> restrictToSurfaces(std::unique_ptr<geom::Geometry> g);
public:
- CascadedPolygonUnion();
/** \brief
* Computes the union of a collection of polygonal [Geometrys](@ref geom::Geometry).
@@ -140,13 +140,13 @@ public:
* @param polys a collection of polygonal [Geometrys](@ref geom::Geometry).
* ownership of elements *and* vector are left to caller.
*/
- static std::unique_ptr<geom::Geometry> Union(std::vector<geom::Polygon*>* polys);
- static std::unique_ptr<geom::Geometry> Union(std::vector<geom::Polygon*>* polys, UnionStrategy* unionFun, geos::util::ProgressFunction* progressFunction);
+ static std::unique_ptr<geom::Geometry> Union(const std::vector<const geom::Surface*>& polys);
+ static std::unique_ptr<geom::Geometry> Union(const std::vector<const geom::Surface*>& polys, UnionStrategy* unionFun, geos::util::ProgressFunction* progressFunction);
/** \brief
- * Computes the union of a set of polygonal [Geometrys](@ref geom::Geometry).
+ * Computes the union of a set of surface [Geometrys](@ref geom::Geometry).
*
- * @tparam T an iterator yielding something castable to const Polygon *
+ * @tparam T an iterator yielding something castable to const Surface*
* @param start start iterator
* @param end end iterator
* @param unionStrategy strategy to apply
@@ -156,12 +156,12 @@ public:
static std::unique_ptr<geom::Geometry>
Union(T start, T end, UnionStrategy *unionStrategy, geos::util::ProgressFunction* progressFunction)
{
- std::vector<geom::Polygon*> polys;
+ std::vector<const geom::Surface*> polys;
for(T i = start; i != end; ++i) {
- const geom::Polygon* p = dynamic_cast<const geom::Polygon*>(*i);
- polys.push_back(const_cast<geom::Polygon*>(p));
+ const auto* p = dynamic_cast<const geom::Surface*>(*i);
+ polys.push_back(p);
}
- return Union(&polys, unionStrategy, progressFunction);
+ return Union(polys, unionStrategy, progressFunction);
}
/** \brief
@@ -177,16 +177,16 @@ public:
* Creates a new instance to union the given collection of
* [Geometrys](@ref geom::Geometry).
*
- * @param polys a collection of polygonal [Geometrys](@ref geom::Geometry).
+ * @param polys a collection of surface [Geometrys](@ref geom::Geometry).
* Ownership of elements *and* vector are left to caller.
*/
- CascadedPolygonUnion(std::vector<geom::Polygon*>* polys)
+ explicit CascadedPolygonUnion(const std::vector<const geom::Surface*>& polys)
: inputPolys(polys)
, geomFactory(nullptr)
, unionFunction(&defaultUnionFunction)
{}
- CascadedPolygonUnion(std::vector<geom::Polygon*>* polys, UnionStrategy* unionFun)
+ CascadedPolygonUnion(const std::vector<const geom::Surface*>& polys, UnionStrategy* unionFun)
: inputPolys(polys)
, geomFactory(nullptr)
, unionFunction(unionFun)
@@ -232,7 +232,7 @@ private:
*/
std::unique_ptr<geom::Geometry> unionSafe(const geom::Geometry* g0, const geom::Geometry* g1) const;
- std::unique_ptr<geom::Geometry> unionSafe(std::unique_ptr<geom::Geometry> &&, std::unique_ptr<geom::Geometry> &&);
+ std::unique_ptr<geom::Geometry> unionSafe(std::unique_ptr<geom::Geometry> &&, std::unique_ptr<geom::Geometry> &&) const;
/**
* Encapsulates the actual unioning of two polygonal geometries.
diff --git a/include/geos/operation/union/UnaryUnionOp.h b/include/geos/operation/union/UnaryUnionOp.h
index 98b6a9e70..39e127d89 100644
--- a/include/geos/operation/union/UnaryUnionOp.h
+++ b/include/geos/operation/union/UnaryUnionOp.h
@@ -171,21 +171,7 @@ private:
}
}
- void
- extract(const geom::Geometry& geom)
- {
- util::ensureNoCurvedComponents(geom);
-
- using namespace geom::util;
-
- if(! geomFact) {
- geomFact = geom.getFactory();
- }
-
- GeometryExtracter::extract<geom::Polygon>(geom, polygons);
- GeometryExtracter::extract<geom::LineString>(geom, lines);
- GeometryExtracter::extract<geom::Point>(geom, points);
- }
+ void extract(const geom::Geometry& geom);
/**
* Computes a unary union with no extra optimization,
@@ -217,14 +203,14 @@ private:
* @return the union of the input(s)
* @return null if both inputs are null
*/
- std::unique_ptr<geom::Geometry> unionWithNull(
+ static std::unique_ptr<geom::Geometry> unionWithNull(
std::unique_ptr<geom::Geometry> g0,
std::unique_ptr<geom::Geometry> g1
);
// Members
- std::vector<const geom::Polygon*> polygons;
- std::vector<const geom::LineString*> lines;
+ std::vector<const geom::Surface*> polygons;
+ std::vector<const geom::Curve*> lines;
std::vector<const geom::Point*> points;
const geom::GeometryFactory* geomFact;
diff --git a/src/operation/union/CascadedPolygonUnion.cpp b/src/operation/union/CascadedPolygonUnion.cpp
index aac120c80..4973124a3 100644
--- a/src/operation/union/CascadedPolygonUnion.cpp
+++ b/src/operation/union/CascadedPolygonUnion.cpp
@@ -21,13 +21,13 @@
#include <geos/geom/Geometry.h>
#include <geos/geom/GeometryFactory.h>
#include <geos/geom/MultiPolygon.h>
+#include <geos/geom/MultiSurface.h>
#include <geos/geom/Polygon.h>
#include <geos/index/strtree/TemplateSTRtree.h>
#include <geos/operation/overlayng/OverlayNG.h>
#include <geos/operation/overlayng/OverlayNGRobust.h>
#include <geos/operation/union/CascadedPolygonUnion.h>
#include <geos/operation/valid/IsValidOp.h>
-#include <geos/operation/valid/IsSimpleOp.h>
#include <geos/util/TopologyException.h>
// std
@@ -44,7 +44,7 @@ namespace geounion { // geos.operation.geounion
// ////////////////////////////////////////////////////////////////////////////
std::unique_ptr<geom::Geometry>
-CascadedPolygonUnion::Union(std::vector<geom::Polygon*>* polys)
+CascadedPolygonUnion::Union(const std::vector<const geom::Surface*>& polys)
{
CascadedPolygonUnion op(polys);
geos::util::ProgressFunction* progressFunction = nullptr;
@@ -52,7 +52,7 @@ CascadedPolygonUnion::Union(std::vector<geom::Polygon*>* polys)
}
std::unique_ptr<geom::Geometry>
-CascadedPolygonUnion::Union(std::vector<geom::Polygon*>* polys, UnionStrategy* unionFun, geos::util::ProgressFunction* progressFunction)
+CascadedPolygonUnion::Union(const std::vector<const geom::Surface*>& polys, UnionStrategy* unionFun, geos::util::ProgressFunction* progressFunction)
{
CascadedPolygonUnion op(polys, unionFun);
return op.Union(progressFunction);
@@ -61,24 +61,24 @@ CascadedPolygonUnion::Union(std::vector<geom::Polygon*>* polys, UnionStrategy* u
std::unique_ptr<geom::Geometry>
CascadedPolygonUnion::Union(const geom::MultiPolygon* multipoly, geos::util::ProgressFunction* progressFunction)
{
- std::vector<geom::Polygon*> polys;
+ std::vector<const geom::Surface*> polys;
for(const auto& g : *multipoly) {
polys.push_back(dynamic_cast<geom::Polygon*>(g.get()));
}
- CascadedPolygonUnion op(&polys);
+ CascadedPolygonUnion op(polys);
return op.Union(progressFunction);
}
std::unique_ptr<geom::Geometry>
CascadedPolygonUnion::Union(geos::util::ProgressFunction* progressFunction)
{
- if(inputPolys->empty()) {
+ if(inputPolys.empty()) {
return nullptr;
}
- geomFactory = inputPolys->front()->getFactory();
+ geomFactory = inputPolys.front()->getFactory();
/*
* A spatial index to organize the collection
@@ -87,8 +87,8 @@ CascadedPolygonUnion::Union(geos::util::ProgressFunction* progressFunction)
* to be eliminated on each round.
*/
- index::strtree::TemplateSTRtree<const geom::Geometry*> index(10, inputPolys->size());
- for (const auto& p : *inputPolys) {
+ index::strtree::TemplateSTRtree<const geom::Geometry*> index(10, inputPolys.size());
+ for (const auto& p : inputPolys) {
index.insert(p);
}
@@ -153,7 +153,7 @@ CascadedPolygonUnion::unionSafe(const geom::Geometry* g0, const geom::Geometry*
}
std::unique_ptr<geom::Geometry>
-CascadedPolygonUnion::unionSafe(std::unique_ptr<geom::Geometry> && g0, std::unique_ptr<geom::Geometry> && g1)
+CascadedPolygonUnion::unionSafe(std::unique_ptr<geom::Geometry> && g0, std::unique_ptr<geom::Geometry> && g1) const
{
if(g0 == nullptr && g1 == nullptr) {
return nullptr;
@@ -174,7 +174,7 @@ CascadedPolygonUnion::unionActual(const geom::Geometry* g0, const geom::Geometry
{
std::unique_ptr<geom::Geometry> ug;
ug = unionFunction->Union(g0, g1);
- return restrictToPolygons(std::move(ug));
+ return restrictToSurfaces(std::move(ug));
}
std::unique_ptr<geom::Geometry>
@@ -182,11 +182,11 @@ CascadedPolygonUnion::unionActual(std::unique_ptr<geom::Geometry> && g0, std::un
{
std::unique_ptr<geom::Geometry> ug;
ug = unionFunction->Union(std::move(g0), std::move(g1));
- return restrictToPolygons(std::move(ug));
+ return restrictToSurfaces(std::move(ug));
}
std::unique_ptr<geom::Geometry>
-CascadedPolygonUnion::restrictToPolygons(std::unique_ptr<geom::Geometry> g)
+CascadedPolygonUnion::restrictToSurfaces(std::unique_ptr<geom::Geometry> g)
{
using namespace geom;
@@ -199,12 +199,19 @@ CascadedPolygonUnion::restrictToPolygons(std::unique_ptr<geom::Geometry> g)
auto coll = dynamic_cast<GeometryCollection*>(g.get());
if (coll) {
- // Release polygons from the collection and re-form into MultiPolygon
+ // Release polygons from the collection and re-form into Surface
auto components = coll->releaseGeometries();
components.erase(std::remove_if(components.begin(), components.end(), [](const std::unique_ptr<Geometry> & cmp) {
return !cmp->isPolygonal();
}), components.end());
+ const bool hasCurves = std::any_of(components.begin(), components.end(), [](const auto & cmp) {
+ return cmp->hasCurvedComponents();
+ });
+
+ if (hasCurves) {
+ return gfact->createMultiSurface(std::move(components));
+ }
return gfact->createMultiPolygon(std::move(components));
} else {
// Not polygonal and not a collection? No polygons here.
diff --git a/src/operation/union/UnaryUnionOp.cpp b/src/operation/union/UnaryUnionOp.cpp
index 7b6601c14..94f1bafff 100644
--- a/src/operation/union/UnaryUnionOp.cpp
+++ b/src/operation/union/UnaryUnionOp.cpp
@@ -34,8 +34,9 @@
#include <geos/geom/GeometryFactory.h>
#include <geos/geom/util/GeometryCombiner.h>
#include <geos/algorithm/PointLocator.h>
+#include <geos/util.h>
-#include "geos/util.h"
+using geos::geom::util::GeometryExtracter;
namespace geos {
namespace operation { // geos::operation
@@ -62,6 +63,18 @@ UnaryUnionOp::unionWithNull(std::unique_ptr<geom::Geometry> g0,
return ret;
}
+void
+UnaryUnionOp::extract(const geom::Geometry& geom)
+{
+ if(! geomFact) {
+ geomFact = geom.getFactory();
+ }
+
+ GeometryExtracter::extract<geom::Surface>(geom, polygons);
+ GeometryExtracter::extract<geom::Curve>(geom, lines);
+ GeometryExtracter::extract<geom::Point>(geom, points);
+}
+
/*public*/
std::unique_ptr<geom::Geometry>
UnaryUnionOp::Union(geos::util::ProgressFunction* progressFunction)
diff --git a/tests/unit/capi/GEOSUnaryUnionTest.cpp b/tests/unit/capi/GEOSUnaryUnionTest.cpp
index 24f99fcb9..af484b8ef 100644
--- a/tests/unit/capi/GEOSUnaryUnionTest.cpp
+++ b/tests/unit/capi/GEOSUnaryUnionTest.cpp
@@ -220,37 +220,15 @@ template<>
template<>
void object::test<12>()
{
- set_test_name("curved inputs");
- useContext();
+ set_test_name("curved dim=1 inputs -> CompoundCurve");
- input_ = fromWKT("MULTICURVE (CIRCULARSTRING (-5 0, 0 5, 5 0), (-5 3, 5 3))");
- ensure(input_);
- GEOSSetSRID_r(ctxt_, input_, 4326);
- double input_length = -1;
- ensure(GEOSLength_r(ctxt_, input_, &input_length));
+ input_ = fromWKT("MULTICURVE (CIRCULARSTRING (-5 0, 0 5, 5 0), (5 0, 5 3))");
- result_ = GEOSUnaryUnion_r(ctxt_, input_);
- ensure(result_ == nullptr);
-
- GEOSCurveToLineParams_setMaxStepDegrees_r(ctxt_, curveToLineParams_, 1);
- GEOSContext_setCurveToLineParams_r(ctxt_, curveToLineParams_);
-
- // Input converted to line, output not converted to curve
- result_ = GEOSUnaryUnion_r(ctxt_, input_);
+ result_ = GEOSUnaryUnion(input_);
ensure(result_);
- ensure_equals(GEOSGeomTypeId_r(ctxt_, result_), GEOS_MULTILINESTRING);
- ensure_equals(GEOSGetSRID_r(ctxt_, result_), 4326);
- GEOSGeom_destroy_r(ctxt_, result_);
- // Input converted to line, output converted to curve
- GEOSContext_setLineToCurveParams_r(ctxt_, lineToCurveParams_);
- result_ = GEOSUnaryUnion_r(ctxt_, input_);
- ensure_equals(GEOSGeomTypeId_r(ctxt_, result_), GEOS_MULTICURVE);
- double result_length = -1;
- ensure(GEOSLength_r(ctxt_, result_, &result_length));
-
- ensure_equals(GEOSGetSRID_r(ctxt_, result_), 4326);
- ensure_equals("length does not match", result_length, input_length, 1e-5);
+ expected_ = fromWKT("COMPOUNDCURVE (CIRCULARSTRING (-5 0, 0 5, 5 0), (5 0, 5 3))");
+ ensure_geometry_equals(result_, expected_);
}
template<>
@@ -308,6 +286,53 @@ void object::test<14>() {
ensure_equals(fracs[0], 1.0);
}
+template<>
+template<>
+void object::test<15>()
+{
+ set_test_name("curved polygonal inputs");
+
+ input_ = fromWKT("MULTISURFACE (CURVEPOLYGON (COMPOUNDCURVE ((5 0, 0 0, 0 5, 5 5), CIRCULARSTRING (5 5, 2.5 2.5, 5 0))), CURVEPOLYGON (COMPOUNDCURVE (CIRCULARSTRING (5 0, 1.5 2.5, 5 5), (5 5, 10 5, 10 0, 5 0))))");
+
+ result_ = GEOSUnaryUnion(input_);
+ ensure(result_);
+
+ expected_ = fromWKT("CURVEPOLYGON (COMPOUNDCURVE ((0 0, 0 5, 3.2857142857 5), CIRCULARSTRING (3.2857142857 5, 4.1428571429 5.1428571429, 5 5), (5 5, 10 5, 10 0, 5 0), CIRCULARSTRING (5 0, 4.1428571429 -0.1428571429, 3.2857142857 0), (3.2857142857 0, 0 0)))");
+ ensure_geometry_equals(result_, expected_, 1e-6);
+}
+
+template<>
+template<>
+void object::test<16>()
+{
+ set_test_name("curved dim=1 inputs -> MultiCurve");
+
+ input_ = fromWKT("MULTICURVE (CIRCULARSTRING (-5 0, 0 5, 5 0), (0 0, 5 5))");
+
+ result_ = GEOSUnaryUnion(input_);
+ ensure(result_);
+
+ expected_ = fromWKT("MULTICURVE (CIRCULARSTRING (3.5355339059 3.5355339059, 4.6193976626 1.9134171618, 5 0), CIRCULARSTRING (-5 0, -1.9134171618 4.6193976626, 3.5355339059 3.5355339059), (3.5355339059 3.5355339059, 5 5), (0 0, 3.5355339059 3.5355339059))");
+ ensure_geometry_equals(result_, expected_, 1e-6);
+}
+
+template<>
+template<>
+void object::test<17>()
+{
+ set_test_name("curved input is not linearized when CurveToLineParams registered with a context");
+ useContext();
+
+ input_ = fromWKT("CIRCULARSTRING (0 0, 1 1, 2 0)");
+
+ GEOSCurveToLineParams_setMaxStepDegrees_r(ctxt_, curveToLineParams_, 45);
+ GEOSContext_setCurveToLineParams_r(ctxt_, curveToLineParams_);
+
+ result_ = GEOSUnaryUnion_r(ctxt_, input_);
+
+ ensure_geometry_equals(result_, input_, 1e-8);
+}
+
} // namespace tut
diff --git a/tests/unit/geom/CircularStringTest.cpp b/tests/unit/geom/CircularStringTest.cpp
index 59f0de931..3be6a7b7e 100644
--- a/tests/unit/geom/CircularStringTest.cpp
+++ b/tests/unit/geom/CircularStringTest.cpp
@@ -169,7 +169,7 @@ void object::test<3>()
ensure("equalsIdentical", cs_->equalsIdentical(cs2.get()));
// Overlay
- ensure_THROW(cs_->Union(), geos::util::UnsupportedOperationException);
+ ensure_equals_geometry(cs_->Union().get(), static_cast<const Geometry*>(cs_.get()));
ensure_equals(cs_->Union(cs_.get())->getLength(), cs_->getLength());
ensure(cs_->difference(cs_.get())->isEmpty());
ensure_equals(cs_->intersection(cs_.get())->getLength(), cs_->getLength());
diff --git a/tests/unit/geom/CompoundCurveTest.cpp b/tests/unit/geom/CompoundCurveTest.cpp
index 79956e095..d6f5cbfde 100644
--- a/tests/unit/geom/CompoundCurveTest.cpp
+++ b/tests/unit/geom/CompoundCurveTest.cpp
@@ -170,11 +170,10 @@ void object::test<3>()
ensure("equalsIdentical", cc_->equalsIdentical(cc2.get()));
// Overlay
- ensure_THROW(cc_->Union(), geos::util::UnsupportedOperationException);
- // TODO: Prevent overlay from degrading CompoundCurve into MultiCurve
- //ensure_equals_geometry(cc_->Union(cc_.get()).get(), static_cast<const Geometry*>(cc_.get()));
+ ensure_equals_geometry(cc_->Union().get(), static_cast<const Geometry*>(cc_.get()));
+ ensure_equals_geometry(cc_->Union(cc_.get()).get(), static_cast<const Geometry*>(cc_.get()));
ensure(cc_->difference(cc_.get())->isEmpty());
- //ensure_equals_geometry(cc_->intersection(cc_.get()).get(), static_cast<const Geometry*>(cc_.get()));
+ ensure_equals_geometry(cc_->intersection(cc_.get()).get(), static_cast<const Geometry*>(cc_.get()));
ensure(cc_->symDifference(cc_.get())->isEmpty());
// Distance
diff --git a/tests/unit/geom/CurvePolygonTest.cpp b/tests/unit/geom/CurvePolygonTest.cpp
index 52eb905b2..562b27637 100644
--- a/tests/unit/geom/CurvePolygonTest.cpp
+++ b/tests/unit/geom/CurvePolygonTest.cpp
@@ -167,7 +167,7 @@ void object::test<3>()
ensure("equalsIdentical", cp_->equalsIdentical(cp2.get()));
// Overlay
- ensure_THROW(cp_->Union(), geos::util::UnsupportedOperationException);
+ ensure_equals_geometry(cp_->Union().get(), static_cast<const Geometry*>(cp_.get()));
ensure_equals(cp_->Union(cp_.get())->getLength(), cp_->getLength());
ensure(cp_->difference(cp_.get())->isEmpty());
ensure_equals(cp_->intersection(cp_.get())->getLength(), cp_->getLength());
diff --git a/tests/unit/geom/MultiCurveTest.cpp b/tests/unit/geom/MultiCurveTest.cpp
index e4f264c8c..3ec6cd3d2 100644
--- a/tests/unit/geom/MultiCurveTest.cpp
+++ b/tests/unit/geom/MultiCurveTest.cpp
@@ -154,11 +154,10 @@ void object::test<3>()
ensure("equalsIdentical", mc_->equalsIdentical(cc2.get()));
// Overlay
- ensure_THROW(mc_->Union(), geos::util::UnsupportedOperationException);
- // TODO: Prevent overlay from degrading CompoundCurve into MultiCurve
- //ensure_equals_geometry(mc_->Union(mc_.get()).get(), static_cast<const Geometry*>(mc_.get()));
+ ensure_equals_geometry(mc_->Union().get(), static_cast<const Geometry*>(mc_.get()));
+ ensure_equals_geometry(mc_->Union(mc_.get()).get(), static_cast<const Geometry*>(mc_.get()));
ensure(mc_->difference(mc_.get())->isEmpty());
- //ensure_equals_geometry(mc_->intersection(mc_.get()).get(), static_cast<const Geometry*>(mc_.get()));
+ ensure_equals_geometry(mc_->intersection(mc_.get()).get(), static_cast<const Geometry*>(mc_.get()));
ensure(mc_->symDifference(mc_.get())->isEmpty());
// Distance
diff --git a/tests/unit/geom/MultiSurfaceTest.cpp b/tests/unit/geom/MultiSurfaceTest.cpp
index 9f84cdc28..46679188e 100644
--- a/tests/unit/geom/MultiSurfaceTest.cpp
+++ b/tests/unit/geom/MultiSurfaceTest.cpp
@@ -143,7 +143,7 @@ void object::test<3>()
ensure("equalsIdentical", ms_->equalsIdentical(cp2.get()));
// Overlay
- ensure_THROW(ms_->Union(), geos::util::UnsupportedOperationException);
+ ensure_equals_geometry(ms_->Union().get(), static_cast<const Geometry*>(ms_.get()));
ensure_equals_geometry(ms_->Union(ms_.get()).get(), static_cast<const Geometry*>(ms_.get()));
ensure(ms_->difference(ms_.get())->isEmpty());
ensure_equals_geometry(ms_->intersection(ms_.get()).get(), static_cast<const Geometry*>(ms_.get()));
diff --git a/tests/unit/operation/geounion/CascadedPolygonUnionTest.cpp b/tests/unit/operation/geounion/CascadedPolygonUnionTest.cpp
index adf5b2628..b084e7f39 100644
--- a/tests/unit/operation/geounion/CascadedPolygonUnionTest.cpp
+++ b/tests/unit/operation/geounion/CascadedPolygonUnionTest.cpp
@@ -42,13 +42,12 @@ typedef group::object object;
group test_cascadedpolygonuniontest_group("geos::operation::geounion::CascadedPolygonUnion");
// test runner
-geos::geom::Geometry*
-unionIterated(
- std::vector<geos::geom::Polygon*>* geoms)
+std::unique_ptr<geos::geom::Geometry>
+unionIterated(const std::vector<const geos::geom::Surface*>& geoms)
{
std::unique_ptr<geos::geom::Geometry> unionAll;
- for(const auto& p : *geoms) {
+ for(const auto& p : geoms) {
if(unionAll == nullptr) {
unionAll = p->clone();
}
@@ -56,20 +55,19 @@ unionIterated(
unionAll = unionAll->Union(p);
}
}
- return unionAll.release();
+ return unionAll;
}
std::unique_ptr<geos::geom::Geometry>
unionCascaded(
- std::vector<geos::geom::Polygon*>* geoms)
+ const std::vector<const geos::geom::Surface*>& geoms)
{
using geos::operation::geounion::CascadedPolygonUnion;
return CascadedPolygonUnion::Union(geoms);
}
void
-p_test_runner(
- std::vector<geos::geom::Polygon*>* geoms)
+p_test_runner(const std::vector<const geos::geom::Surface*>& geoms)
{
std::unique_ptr<geos::geom::Geometry> union1(unionIterated(geoms));
std::unique_ptr<geos::geom::Geometry> union2(unionCascaded(geoms));
@@ -78,12 +76,6 @@ p_test_runner(
ensure_equals_geometry(union1.get(), union2.get(), 0.000001);
}
-void
-delete_geometry(geos::geom::Geometry* g)
-{
- delete g;
-}
-
//
// Test Cases
//
@@ -100,7 +92,7 @@ void object::test<1>
nullptr
};
- std::vector<geos::geom::Polygon*> g;
+ std::vector<const geos::geom::Surface*> g;
for(char const * const* p = polygons; *p != nullptr; ++p) {
std::string wkt(*p);
geos::geom::Polygon* geom =
@@ -108,9 +100,11 @@ void object::test<1>
g.push_back(geom);
}
- p_test_runner(&g);
+ p_test_runner(g);
- for_each(g.begin(), g.end(), delete_geometry);
+ for (auto& p : g) {
+ delete p;
+ }
}
void
-----------------------------------------------------------------------
Summary of changes:
capi/geos_ts_c.cpp | 7 +-
.../geos/operation/union/CascadedPolygonUnion.h | 42 ++++++------
include/geos/operation/union/UnaryUnionOp.h | 22 ++----
src/operation/union/CascadedPolygonUnion.cpp | 35 ++++++----
src/operation/union/UnaryUnionOp.cpp | 15 +++-
tests/unit/capi/GEOSUnaryUnionTest.cpp | 79 ++++++++++++++--------
tests/unit/geom/CircularStringTest.cpp | 2 +-
tests/unit/geom/CompoundCurveTest.cpp | 7 +-
tests/unit/geom/CurvePolygonTest.cpp | 2 +-
tests/unit/geom/MultiCurveTest.cpp | 7 +-
tests/unit/geom/MultiSurfaceTest.cpp | 2 +-
.../geounion/CascadedPolygonUnionTest.cpp | 28 +++-----
12 files changed, 136 insertions(+), 112 deletions(-)
hooks/post-receive
--
GEOS
More information about the geos-commits
mailing list