[geos-commits] [SCM] GEOS branch main updated. 637142a36e34062f32fd2c94f7e37d2c8259becb
git at osgeo.org
git at osgeo.org
Mon Mar 9 05:51:38 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 637142a36e34062f32fd2c94f7e37d2c8259becb (commit)
from a1ade8d631190782a6032f2105f4727ead0fb5f3 (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 637142a36e34062f32fd2c94f7e37d2c8259becb
Author: Daniel Baston <dbaston at gmail.com>
Date: Mon Mar 9 08:51:17 2026 -0400
CurvePolygon: throw construction exception on non-closed ring (#1393)
diff --git a/include/geos/geom/Surface.h b/include/geos/geom/Surface.h
index d2dcb384e..35e0d9cf1 100644
--- a/include/geos/geom/Surface.h
+++ b/include/geos/geom/Surface.h
@@ -109,6 +109,8 @@ protected:
void geometryChangedAction() override {}
+ void validateConstruction() const;
+
};
}
diff --git a/include/geos/geom/SurfaceImpl.h b/include/geos/geom/SurfaceImpl.h
index 60da401ef..fc66a1a87 100644
--- a/include/geos/geom/SurfaceImpl.h
+++ b/include/geos/geom/SurfaceImpl.h
@@ -70,6 +70,8 @@ protected:
if (shell == nullptr) {
shell.reset(static_cast<RingType*>(createEmptyRing(newFactory).release()));
}
+
+ validateConstruction();
}
SurfaceImpl(std::unique_ptr<RingType>&& newShell,
@@ -83,12 +85,7 @@ protected:
shell.reset(static_cast<RingType*>(createEmptyRing(newFactory).release()));
}
- if(shell->isEmpty() && hasNonEmptyElements(&holes)) {
- throw geos::util::IllegalArgumentException("shell is empty but holes are not");
- }
- if (hasNullElements(&holes)) {
- throw geos::util::IllegalArgumentException("holes must not contain null elements");
- }
+ validateConstruction();
}
public:
diff --git a/src/geom/Surface.cpp b/src/geom/Surface.cpp
index 34bb5c601..9a5d66277 100644
--- a/src/geom/Surface.cpp
+++ b/src/geom/Surface.cpp
@@ -282,5 +282,30 @@ Surface::isEmpty() const
return getExteriorRing()->isEmpty();
}
+void
+Surface::validateConstruction() const
+{
+ const bool shellIsEmpty = getExteriorRing()->isEmpty();
+
+ if (!shellIsEmpty && !getExteriorRing()->isClosed()) {
+ throw util::IllegalArgumentException("Exterior ring is not closed");
+ }
+
+ for (std::size_t i = 0 ; i < getNumInteriorRing(); i++) {
+ const Curve* hole = getInteriorRingN(i);
+
+ if (hole == nullptr) {
+ throw util::IllegalArgumentException("holes must not contain null elements");
+ }
+
+ if (shellIsEmpty && !hole->isEmpty()) {
+ throw util::IllegalArgumentException("shell is empty but holes are not");
+ }
+
+ if (!hole->isClosed()) {
+ throw util::IllegalArgumentException("Hole is not closed");
+ }
+ }
+}
}
}
diff --git a/tests/unit/capi/GEOSisValidDetailTest.cpp b/tests/unit/capi/GEOSisValidDetailTest.cpp
index 4c0c12e9e..a4f8e3a38 100644
--- a/tests/unit/capi/GEOSisValidDetailTest.cpp
+++ b/tests/unit/capi/GEOSisValidDetailTest.cpp
@@ -144,7 +144,7 @@ template<>
template<>
void object::test<7>()
{
- input_ = fromWKT("CURVEPOLYGON (COMPOUNDCURVE( CIRCULARSTRING (0 0, 1 1, 2 0), (2 0, 1 1)))");
+ input_ = fromWKT("CURVEPOLYGON (COMPOUNDCURVE( CIRCULARSTRING (0 0, 1 1, 2 0), (2 0, 0 0)))");
ensure(input_ != nullptr);
char ret = GEOSisValidDetail(input_, 0, nullptr, nullptr);
diff --git a/tests/unit/capi/GEOSisValidReasonTest.cpp b/tests/unit/capi/GEOSisValidReasonTest.cpp
index fbd988e59..e3146c443 100644
--- a/tests/unit/capi/GEOSisValidReasonTest.cpp
+++ b/tests/unit/capi/GEOSisValidReasonTest.cpp
@@ -61,7 +61,7 @@ template<>
template<>
void object::test<7>()
{
- input_ = fromWKT("CURVEPOLYGON (COMPOUNDCURVE( CIRCULARSTRING (0 0, 1 1, 2 0), (2 0, 1 1)))");
+ input_ = fromWKT("CURVEPOLYGON (COMPOUNDCURVE( CIRCULARSTRING (0 0, 1 1, 2 0), (2 0, 0 0)))");
ensure(input_ != nullptr);
char* reason = GEOSisValidReason(input_);
diff --git a/tests/unit/capi/GEOSisValidTest.cpp b/tests/unit/capi/GEOSisValidTest.cpp
index a71fc5150..046a53feb 100644
--- a/tests/unit/capi/GEOSisValidTest.cpp
+++ b/tests/unit/capi/GEOSisValidTest.cpp
@@ -68,7 +68,7 @@ template<>
template<>
void object::test<5>()
{
- input_ = fromWKT("CURVEPOLYGON (COMPOUNDCURVE( CIRCULARSTRING (0 0, 1 1, 2 0), (2 0, 1 1)))");
+ input_ = fromWKT("CURVEPOLYGON (COMPOUNDCURVE( CIRCULARSTRING (0 0, 1 1, 2 0), (2 0, 0 0)))");
ensure(input_ != nullptr);
char ret = GEOSisValid(input_);
diff --git a/tests/unit/geom/CurvePolygonTest.cpp b/tests/unit/geom/CurvePolygonTest.cpp
index 774a8bb32..ebddf3328 100644
--- a/tests/unit/geom/CurvePolygonTest.cpp
+++ b/tests/unit/geom/CurvePolygonTest.cpp
@@ -198,4 +198,41 @@ void object::test<4>()
ensure_equals("cpRev->getArea()", cpRev->getArea(), 9.8185835, 1e-6);
}
+template<>
+template<>
+void object::test<5>()
+{
+ set_test_name("construction error on non-closed ring");
+
+ auto seq = std::make_unique<geos::geom::CoordinateSequence>(3);
+ seq->setAt(CoordinateXY{0, 0}, 0);
+ seq->setAt(CoordinateXY{1, 1}, 1);
+ seq->setAt(CoordinateXY{2, 0}, 2);
+ auto cs = factory_->createCircularString(std::move(seq));
+
+ seq = std::make_unique<geos::geom::CoordinateSequence>(2);
+ seq->setAt(CoordinateXY{2, 0}, 0);
+ seq->setAt(CoordinateXY{1, 0}, 1);
+ auto ls = factory_->createLineString(std::move(seq));
+
+ std::vector<std::unique_ptr<geos::geom::SimpleCurve>> curves;
+ curves.push_back(std::move(cs));
+ curves.push_back(std::move(ls));
+
+ auto cc = factory_->createCompoundCurve(std::move(curves));
+
+ // shell is non-closed
+ ensure_THROW(factory_->createCurvePolygon(std::move(cc)), geos::util::IllegalArgumentException);
+
+ geos::geom::Envelope shellEnv(-100, 100, -100, 100);
+ auto shell = static_cast<const geos::geom::Polygon*>(factory_->toGeometry(&shellEnv).get())->getExteriorRing()->clone();
+
+ std::vector<std::unique_ptr<geos::geom::Curve>> holes;
+ holes.push_back(std::move(cc));
+
+ // hole is non-cloesd
+ ensure_THROW(factory_->createCurvePolygon(std::move(shell), std::move(holes)), geos::util::IllegalArgumentException);
+}
+
+
}
-----------------------------------------------------------------------
Summary of changes:
include/geos/geom/Surface.h | 2 ++
include/geos/geom/SurfaceImpl.h | 9 +++-----
src/geom/Surface.cpp | 25 +++++++++++++++++++++
tests/unit/capi/GEOSisValidDetailTest.cpp | 2 +-
tests/unit/capi/GEOSisValidReasonTest.cpp | 2 +-
tests/unit/capi/GEOSisValidTest.cpp | 2 +-
tests/unit/geom/CurvePolygonTest.cpp | 37 +++++++++++++++++++++++++++++++
7 files changed, 70 insertions(+), 9 deletions(-)
hooks/post-receive
--
GEOS
More information about the geos-commits
mailing list