From 136e8e486f13e590da6096c196c49bc6ca272b2c Mon Sep 17 00:00:00 2001 From: Martin Davis Date: Tue, 5 Dec 2023 12:53:12 -0800 Subject: [PATCH] Fix PreparedPolygonContains for GC with MultiPoint (#1008) --- src/geom/prep/AbstractPreparedPolygonContains.cpp | 14 ++++++-------- tests/unit/geom/prep/PreparedGeometryTest.cpp | 14 ++++++++++++++ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/geom/prep/AbstractPreparedPolygonContains.cpp b/src/geom/prep/AbstractPreparedPolygonContains.cpp index cfc87436cd..f0dbdeacc3 100644 --- a/src/geom/prep/AbstractPreparedPolygonContains.cpp +++ b/src/geom/prep/AbstractPreparedPolygonContains.cpp @@ -186,7 +186,6 @@ bool AbstractPreparedPolygonContains::evalPointTestGeom(const Geometry *geom, Lo if (outermostLoc == Location::EXTERIOR) { return false; } - // For the Covers predicate, we can return true // since no Points are on the exterior of the target // geometry. @@ -195,19 +194,18 @@ bool AbstractPreparedPolygonContains::evalPointTestGeom(const Geometry *geom, Lo } // For the Contains predicate, we need to test if any - // of those points lie in the interior of the target + // of the test points lie in the interior of the target // geometry. if (outermostLoc == Location::INTERIOR) { return true; } - if (geom->getNumGeometries() > 1) { - // for MultiPoint, try to find at least one point - // in interior - return isAnyTestComponentInTargetInterior(geom); + // a single point must not be in interior + if (geom->getNumPoints() <= 1) { + return false; } - - return false; + // for multiple points have to check all + return isAnyTestComponentInTargetInterior(geom); } // diff --git a/tests/unit/geom/prep/PreparedGeometryTest.cpp b/tests/unit/geom/prep/PreparedGeometryTest.cpp index ffdd90faf0..c1df1abac4 100644 --- a/tests/unit/geom/prep/PreparedGeometryTest.cpp +++ b/tests/unit/geom/prep/PreparedGeometryTest.cpp @@ -84,5 +84,19 @@ void object::test<2> ensure( pg1->intersects(g2.get()) ); } +// See https://github.com/libgeos/geos/issues/1007 +template<> +template<> +void object::test<3> +() +{ + g1 = reader.read( "MULTIPOLYGON(((-60 -50,-70 -50,-60 -40,-60 -50)))" ); + g2 = reader.read( "GEOMETRYCOLLECTION(MULTIPOINT((-60 -50),(-63 -49)))" ); + + pg1 = prep::PreparedGeometryFactory::prepare(g1.get()); + + ensure( g1->contains(g2.get()) ); + ensure( pg1->contains(g2.get()) ); +} } // namespace tut