[geos-commits] [SCM] GEOS branch main updated. 979185683c608440f7dc36cec1474a5c2ab90b8a
git at osgeo.org
git at osgeo.org
Thu Sep 10 07:46:44 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 979185683c608440f7dc36cec1474a5c2ab90b8a (commit)
via 52c59386decedfb44594de1d9f9d78e730743a26 (commit)
from 55809ca8d7e904c363d715791e956875b019221b (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 979185683c608440f7dc36cec1474a5c2ab90b8a
Author: Daniel Baston <dbaston at gmail.com>
Date: Tue Sep 8 16:09:15 2026 -0400
GeometrySplitter: Add tests for MultiSurface-LineString split
diff --git a/tests/unit/operation/split/GeometrySplitterTest.cpp b/tests/unit/operation/split/GeometrySplitterTest.cpp
index 4e91f7230..8209abca4 100644
--- a/tests/unit/operation/split/GeometrySplitterTest.cpp
+++ b/tests/unit/operation/split/GeometrySplitterTest.cpp
@@ -925,4 +925,15 @@ void object::test<76>()
ensure_THROW(GeometrySplitter::split(*poly, *line), geos::util::GEOSException);
}
+template<>
+template<>
+void object::test<77>()
+{
+ set_test_name("split MultiSurface with LineString");
+
+ testSplit("MULTISURFACE(CURVEPOLYGON (COMPOUNDCURVE((5 0, 0 0, 0 5, 5 5), CIRCULARSTRING(5 5, 7 1, 5 0))))",
+ "LINESTRING(3 6, 3 -1)",
+ "GEOMETRYCOLLECTION (CURVEPOLYGON (COMPOUNDCURVE ((5 0, 3 0, 3 5, 5 5), CIRCULARSTRING (5 5, 7 1, 5 0))), POLYGON ((3 0, 0 0, 0 5, 3 5, 3 0)))");
+}
+
}
commit 52c59386decedfb44594de1d9f9d78e730743a26
Author: Daniel Baston <dbaston at gmail.com>
Date: Fri Oct 31 09:21:27 2025 -0400
Geometry::intersects: handle MultiSurface PIP
diff --git a/include/geos/algorithm/locate/SimplePointInAreaLocator.h b/include/geos/algorithm/locate/SimplePointInAreaLocator.h
index be77ff9d6..11fe95d7d 100644
--- a/include/geos/algorithm/locate/SimplePointInAreaLocator.h
+++ b/include/geos/algorithm/locate/SimplePointInAreaLocator.h
@@ -87,6 +87,10 @@ public:
static bool isContained(const geom::CoordinateXY& p,
const geom::Geometry* geom);
+ static bool isAnyPointContained(const geom::Geometry& pt, const geom::Geometry& areaGeom);
+
+ static bool isEveryPointContained(const geom::Geometry& pt, const geom::Geometry& areaGeom);
+
SimplePointInAreaLocator(const geom::Geometry* p_g)
: g(p_g)
{ }
diff --git a/src/algorithm/locate/SimplePointInAreaLocator.cpp b/src/algorithm/locate/SimplePointInAreaLocator.cpp
index 0a7b8e343..a045f2eff 100644
--- a/src/algorithm/locate/SimplePointInAreaLocator.cpp
+++ b/src/algorithm/locate/SimplePointInAreaLocator.cpp
@@ -18,10 +18,8 @@
#include <geos/algorithm/locate/SimplePointInAreaLocator.h>
#include <geos/geom/Geometry.h>
#include <geos/geom/Polygon.h>
-#include <geos/geom/GeometryCollection.h>
#include <geos/geom/Location.h>
-#include <geos/geom/CoordinateSequence.h>
-#include <geos/geom/LineString.h>
+#include <geos/util/Assert.h>
using namespace geos::geom;
@@ -46,6 +44,42 @@ SimplePointInAreaLocator::isContained(const CoordinateXY& p, const Geometry* geo
return Location::EXTERIOR != locate(p, geom);
}
+bool
+SimplePointInAreaLocator::isAnyPointContained(const geom::Geometry& pt, const geom::Geometry& area)
+{
+ util::Assert::isTrue(area.getDimension() == Dimension::A);
+ util::Assert::isTrue(pt.getDimension() == Dimension::P);
+
+ if (pt.getNumGeometries() > 1) {
+ for (size_t i = 0; i < pt.getNumGeometries(); i++ ) {
+ if (isAnyPointContained(*pt.getGeometryN(i), area)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ return isContained(*pt.getCoordinate(), &area);
+}
+
+bool
+SimplePointInAreaLocator::isEveryPointContained(const geom::Geometry &pt, const geom::Geometry &area)
+{
+ util::Assert::isTrue(area.getDimension() == Dimension::A);
+ util::Assert::isTrue(pt.getDimension() == Dimension::P);
+
+ if (pt.getNumGeometries() > 1) {
+ for (size_t i = 0; i < pt.getNumGeometries(); i++ ) {
+ if (!isEveryPointContained(*pt.getGeometryN(i), area)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ return isContained(*pt.getCoordinate(), &area);
+}
+
geom::Location
SimplePointInAreaLocator::locateInGeometry(const CoordinateXY& p, const Geometry* geom)
{
diff --git a/src/geom/Geometry.cpp b/src/geom/Geometry.cpp
index 72ea87ae9..26c68ae62 100644
--- a/src/geom/Geometry.cpp
+++ b/src/geom/Geometry.cpp
@@ -261,6 +261,10 @@ Geometry::getEnvelope() const
bool
Geometry::disjoint(const Geometry* g) const
{
+ if (hasCurvedComponents() || g->hasCurvedComponents()) {
+ return !intersects(g);
+ }
+
#if USE_RELATENG
return operation::relateng::RelateNG::disjoint(this, g);
#else
@@ -323,13 +327,13 @@ Geometry::intersects(const Geometry* g) const
return predicate::RectangleIntersects::intersects(*p, *this);
}
- auto typ = getGeometryTypeId();
- if (typ == GEOS_CURVEPOLYGON && g->getGeometryTypeId() == GEOS_POINT) {
- auto loc = locate::SimplePointInAreaLocator::locatePointInSurface(*g->getCoordinate(), *detail::down_cast<const Surface*>(this));
- return loc != Location::EXTERIOR;
- } else if (typ == GEOS_POINT && g->getGeometryTypeId() == GEOS_CURVEPOLYGON) {
- auto loc = locate::SimplePointInAreaLocator::locatePointInSurface(*getCoordinate(), *detail::down_cast<const Surface*>(g));
- return loc != Location::EXTERIOR;
+ if (hasCurvedComponents() || g->hasCurvedComponents()) {
+ if (isDimensionStrict(Dimension::A) && g->getDimension() == Dimension::P) {
+ return locate::SimplePointInAreaLocator::isAnyPointContained(*g, *this);
+ }
+ if (g->isDimensionStrict(Dimension::A) && getDimension() == Dimension::P) {
+ return locate::SimplePointInAreaLocator::isAnyPointContained(*this, *g);
+ }
}
#if USE_RELATENG
diff --git a/tests/unit/algorithm/locate/SimplePointInAreaLocatorTest.cpp b/tests/unit/algorithm/locate/SimplePointInAreaLocatorTest.cpp
index 798df3ca6..399e9b332 100644
--- a/tests/unit/algorithm/locate/SimplePointInAreaLocatorTest.cpp
+++ b/tests/unit/algorithm/locate/SimplePointInAreaLocatorTest.cpp
@@ -1,4 +1,5 @@
#include <tut/tut.hpp>
+#include <tut/tut_macros.hpp>
#include <geos/algorithm/locate/SimplePointInAreaLocator.h>
#include <geos/geom/Location.h>
@@ -6,6 +7,7 @@
using geos::geom::CoordinateXY;
using geos::geom::Location;
+using geos::algorithm::locate::SimplePointInAreaLocator;
namespace tut {
@@ -39,4 +41,40 @@ void object::test<1>()
checkLocation(*g, {2.5, 1.5}, Location::EXTERIOR); // inside hole
}
+template<>
+template<>
+void object::test<2>()
+{
+ auto point = reader.read("POINT (1 1)");
+ auto point2 = reader.read("POINT (100 100)");
+ auto multiPoint = reader.read("MULTIPOINT (1 1, 11 11)");
+ auto multiPoint2 = reader.read("MULTIPOINT (100 100, 200 200)");
+ auto poly = reader.read("POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))");
+ auto multiPoly = reader.read("MULTIPOLYGON (((0 0, 10 0, 10 10, 0 10, 0 0)), ((10 10, 20 10, 20 20, 10 20, 10 10)))");
+
+ // isAnyPointContained
+ ensure(SimplePointInAreaLocator::isAnyPointContained(*point, *poly));
+ ensure(SimplePointInAreaLocator::isAnyPointContained(*point, *multiPoly));
+ ensure(SimplePointInAreaLocator::isAnyPointContained(*multiPoint, *poly));
+ ensure(SimplePointInAreaLocator::isAnyPointContained(*multiPoint, *multiPoly));
+ ensure(!SimplePointInAreaLocator::isAnyPointContained(*point2, *poly));
+ ensure(!SimplePointInAreaLocator::isAnyPointContained(*point2, *multiPoly));
+ ensure(!SimplePointInAreaLocator::isAnyPointContained(*multiPoint2, *poly));
+ ensure(!SimplePointInAreaLocator::isAnyPointContained(*multiPoint2, *multiPoly));
+
+ // isEveryPointContained
+ ensure(SimplePointInAreaLocator::isEveryPointContained(*point, *poly));
+ ensure(SimplePointInAreaLocator::isEveryPointContained(*point, *multiPoly));
+ ensure(!SimplePointInAreaLocator::isEveryPointContained(*multiPoint, *poly));
+ ensure(SimplePointInAreaLocator::isEveryPointContained(*multiPoint, *multiPoly));
+ ensure(!SimplePointInAreaLocator::isEveryPointContained(*point2, *poly));
+ ensure(!SimplePointInAreaLocator::isEveryPointContained(*point2, *multiPoly));
+ ensure(!SimplePointInAreaLocator::isEveryPointContained(*multiPoint2, *poly));
+ ensure(!SimplePointInAreaLocator::isEveryPointContained(*multiPoint2, *multiPoly));
+
+ // argument order reversed
+ ensure_THROW(SimplePointInAreaLocator::isAnyPointContained(*poly, *point), geos::util::GEOSException);
+ ensure_THROW(SimplePointInAreaLocator::isEveryPointContained(*poly, *point), geos::util::GEOSException);
+}
+
}
diff --git a/tests/unit/capi/GEOSDisjointTest.cpp b/tests/unit/capi/GEOSDisjointTest.cpp
index 19b8fe138..24fd1eba0 100644
--- a/tests/unit/capi/GEOSDisjointTest.cpp
+++ b/tests/unit/capi/GEOSDisjointTest.cpp
@@ -58,5 +58,18 @@ void object::test<3>()
ensure_equals(0, GEOSDisjoint_r(ctxt_, geom1_, geom2_));
}
+template<>
+template<>
+void object::test<4>()
+{
+ set_test_name("MultiSurface / MultiPoint PIP");
+
+ geom1_ = fromWKT("MULTISURFACE(POLYGON ((100 100, 200 100, 200 200, 100 100)), CURVEPOLYGON (COMPOUNDCURVE(CIRCULARSTRING(0 0, 1 1, 2 0), (2 0, 0 0))))");
+ geom2_ = fromWKT("MULTIPOINT ((5000 5000), (0.1556955 0.5355459))");
+
+ ensure_equals(GEOSDisjoint(geom1_, geom2_), 0);
+ ensure_equals(GEOSDisjoint(geom2_, geom1_), 0);
+}
+
} // namespace tut
diff --git a/tests/unit/capi/GEOSIntersectsTest.cpp b/tests/unit/capi/GEOSIntersectsTest.cpp
index f11ac8615..63631bfca 100644
--- a/tests/unit/capi/GEOSIntersectsTest.cpp
+++ b/tests/unit/capi/GEOSIntersectsTest.cpp
@@ -236,8 +236,8 @@ template<>
template<>
void object::test<12>()
{
- geom1_ = fromWKT("CURVEPOLYGON (COMPOUNDCURVE(CIRCULARSTRING(0 0, 1 1, 2 0), (2 0, 0 0)))");
- geom2_ = fromWKT("POINT (0.1556955 0.5355459)");
+ geom1_ = fromWKT("MULTISURFACE(POLYGON ((100 100, 200 100, 200 200, 100 100)), CURVEPOLYGON (COMPOUNDCURVE(CIRCULARSTRING(0 0, 1 1, 2 0), (2 0, 0 0))))");
+ geom2_ = fromWKT("MULTIPOINT ((5000 5000), (0.1556955 0.5355459))");
// PostGIS would return false here because geom2 is inside geom1
// but outside the linearized form of geom1
@@ -272,5 +272,32 @@ void object::test<14>()
ensure_equals(1, GEOSIntersects_r(ctxt_, geom1_, geom2_));
}
+template<>
+template<>
+void object::test<15>()
+{
+ set_test_name("PostGIS ticket 5832");
+
+ geom1_ = fromWKT("MULTISURFACE(CURVEPOLYGON(COMPOUNDCURVE((25492739.7449 6677441.1816,25492771.1213 6677416.7832),CIRCULARSTRING(25492771.1213 6677416.7832,25492832.3384 6677400.8583,25492885.9851 6677434.3719),(25492885.9851 6677434.3719,25492900.7986 6677455.7498),CIRCULARSTRING(25492900.7986 6677455.7498,25492901.1068 6677457.3233,25492900.1601 6677458.6175,25492822.2626 6677477.2365,25492747.0232 6677449.7828),(25492747.0232 6677449.7828,25492739.7748 6677444.3615),CIRCULARSTRING(25492739.7748 6677444.3615,25492738.9731 6677442.7789,25492739.7449 6677441.1816))))");
+ geom2_ = fromWKT("POINT (25492818 6677399.98)");
+
+ ensure_equals(GEOSIntersects(geom1_, geom2_), 1);
+ ensure_equals(GEOSIntersects(geom2_, geom1_), 1);
+}
+
+template<>
+template<>
+void object::test<16>()
+{
+ set_test_name("mixed-dimension collection with point");
+
+ geom1_ = fromWKT("GEOMETRYCOLLECTION (CURVEPOLYGON (COMPOUNDCURVE(CIRCULARSTRING (-5 0, 0 5, 5 0), (5 0, -5 0))), LINESTRING (10 10, 11 11))");
+ geom2_ = fromWKT("POINT (11 11)");
+
+ // can't rely on PIP with mixed-dimension input, so return error for now
+ ensure_equals(GEOSIntersects(geom1_, geom2_), 2);
+ ensure_equals(GEOSIntersects(geom2_, geom1_), 2);
+}
+
} // namespace tut
-----------------------------------------------------------------------
Summary of changes:
.../algorithm/locate/SimplePointInAreaLocator.h | 4 +++
src/algorithm/locate/SimplePointInAreaLocator.cpp | 40 ++++++++++++++++++++--
src/geom/Geometry.cpp | 18 ++++++----
.../locate/SimplePointInAreaLocatorTest.cpp | 38 ++++++++++++++++++++
tests/unit/capi/GEOSDisjointTest.cpp | 13 +++++++
tests/unit/capi/GEOSIntersectsTest.cpp | 31 +++++++++++++++--
.../unit/operation/split/GeometrySplitterTest.cpp | 11 ++++++
7 files changed, 143 insertions(+), 12 deletions(-)
hooks/post-receive
--
GEOS
More information about the geos-commits
mailing list