Skip to content

Commit

Permalink
upgrade geos, apply distance patch
Browse files Browse the repository at this point in the history
  • Loading branch information
Maxxen committed Nov 3, 2023
1 parent 9266dba commit 8d3e9fd
Show file tree
Hide file tree
Showing 5 changed files with 277 additions and 1 deletion.
3 changes: 2 additions & 1 deletion deps/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,9 @@ set(GDAL_DEPENDENCIES ${GDAL_DEPENDENCIES} EXPAT)
# GEOS
ExternalProject_Add(
GEOS
URL ${CMAKE_CURRENT_SOURCE_DIR}/vendor/geos-3.11.2.tar.bz2
URL ${CMAKE_CURRENT_SOURCE_DIR}/vendor/geos-3.12.0.tar.bz2
CONFIGURE_HANDLED_BY_BUILD TRUE
PATCH_COMMAND patch -p1 < "${CMAKE_CURRENT_LIST_DIR}/patches/geos_distance.patch"
CMAKE_ARGS
# CMake options
-DCMAKE_INSTALL_PREFIX:PATH=${LOCAL_INSTALL_DIR}
Expand Down
274 changes: 274 additions & 0 deletions deps/patches/geos_distance.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,274 @@
From 13c25a877704327db9f4f0dfd9c41d527dc8f46d Mon Sep 17 00:00:00 2001
From: Paul Ramsey <[email protected]>
Date: Thu, 2 Nov 2023 14:45:36 -0700
Subject: [PATCH] Skip over testing empty distances for mixed collections.
Closes #979

---
src/operation/distance/DistanceOp.cpp | 16 +++--
.../operation/distance/DistanceOpTest.cpp | 68 +++++++++++++++++++
.../xmltester/tests/general/TestDistance.xml | 67 +++++++++++++++++-
3 files changed, 145 insertions(+), 6 deletions(-)

diff --git a/src/operation/distance/DistanceOp.cpp b/src/operation/distance/DistanceOp.cpp
index 2f3cb66638..952c68d96c 100644
--- a/src/operation/distance/DistanceOp.cpp
+++ b/src/operation/distance/DistanceOp.cpp
@@ -358,6 +358,10 @@ DistanceOp::computeMinDistanceLines(
{
for(const LineString* line0 : lines0) {
for(const LineString* line1 : lines1) {
+
+ if (line0->isEmpty() || line1->isEmpty())
+ continue;
+
computeMinDistance(line0, line1, locGeom);
if(minDistance <= terminateDistance) {
return;
@@ -374,13 +378,11 @@ DistanceOp::computeMinDistancePoints(
std::array<std::unique_ptr<GeometryLocation>, 2> & locGeom)
{
for(const Point* pt0 : points0) {
- if (pt0->isEmpty()) {
- continue;
- }
for(const Point* pt1 : points1) {
- if (pt1->isEmpty()) {
+
+ if (pt1->isEmpty() || pt0->isEmpty())
continue;
- }
+
double dist = pt0->getCoordinate()->distance(*(pt1->getCoordinate()));

#if GEOS_DEBUG
@@ -414,6 +416,10 @@ DistanceOp::computeMinDistanceLinesPoints(
{
for(const LineString* line : lines) {
for(const Point* pt : points) {
+
+ if (line->isEmpty() || pt->isEmpty())
+ continue;
+
computeMinDistance(line, pt, locGeom);
if(minDistance <= terminateDistance) {
return;
diff --git a/tests/unit/operation/distance/DistanceOpTest.cpp b/tests/unit/operation/distance/DistanceOpTest.cpp
index 9b862e377a..9df481a397 100644
--- a/tests/unit/operation/distance/DistanceOpTest.cpp
+++ b/tests/unit/operation/distance/DistanceOpTest.cpp
@@ -565,6 +565,11 @@ void object::test<21>()
ensure_equals(g1->distance(g2.get()), 1.9996999774966246);
}

+//
+// Variations on a theme: testing EMPTY and collections with EMPTY
+//
+
+// Ignoring empty component
template<>
template<>
void object::test<22>()
@@ -576,6 +581,69 @@ void object::test<22>()
ensure_equals(g2->distance(g1.get()), 1);
}

+// Empty is same as empty so zero...?
+template<>
+template<>
+void object::test<23>()
+{
+ auto g1 = wktreader.read("POINT EMPTY");
+ auto g2 = wktreader.read("LINESTRING EMPTY");
+
+ ensure(g1 != nullptr && g2 != nullptr);
+ ensure_equals(g1->distance(g2.get()), 0);
+ ensure_equals(g2->distance(g1.get()), 0);
+}
+
+template<>
+template<>
+void object::test<24>()
+{
+ auto g1 = wktreader.read("GEOMETRYCOLLECTION(POINT EMPTY, LINESTRING EMPTY)");
+ auto g2 = wktreader.read("LINESTRING EMPTY");
+
+ ensure(g1 != nullptr && g2 != nullptr);
+ ensure_equals(g1->distance(g2.get()), 0);
+ ensure_equals(g2->distance(g1.get()), 0);
+}
+
+// But ignore empty if there's a real distance?
+template<>
+template<>
+void object::test<25>()
+{
+ auto g1 = wktreader.read("GEOMETRYCOLLECTION(LINESTRING EMPTY, POINT(2 1))");
+ auto g2 = wktreader.read("POINT(1 1)");
+
+ ensure(g1 != nullptr && g2 != nullptr);
+ ensure_equals(g1->distance(g2.get()), 1);
+ ensure_equals(g2->distance(g1.get()), 1);
+}
+
+template<>
+template<>
+void object::test<26>()
+{
+ auto g1 = wktreader.read("GEOMETRYCOLLECTION(POINT(-2 0), POINT EMPTY)");
+ auto g2 = wktreader.read("GEOMETRYCOLLECTION(POINT(1 0),LINESTRING(0 0,1 0))");
+
+ ensure(g1 != nullptr && g2 != nullptr);
+ ensure_equals(g1->distance(g2.get()), 2);
+ ensure_equals(g2->distance(g1.get()), 2);
+}
+
+template<>
+template<>
+void object::test<27>()
+{
+ auto g1 = wktreader.read("GEOMETRYCOLLECTION(POINT EMPTY)");
+ auto g2 = wktreader.read("GEOMETRYCOLLECTION(POINT(1 0))");
+
+ ensure(g1 != nullptr && g2 != nullptr);
+ ensure_equals(g1->distance(g2.get()), 0);
+ ensure_equals(g2->distance(g1.get()), 0);
+}
+
+
// TODO: finish the tests by adding:
// LINESTRING - *all*
// MULTILINESTRING - *all*
diff --git a/tests/xmltester/tests/general/TestDistance.xml b/tests/xmltester/tests/general/TestDistance.xml
index 4ce6d0fede..3835c919da 100644
--- a/tests/xmltester/tests/general/TestDistance.xml
+++ b/tests/xmltester/tests/general/TestDistance.xml
@@ -6,6 +6,7 @@
<a> POINT(10 10) </a>
<b> POINT EMPTY </b>
<test><op name="distance" arg1="A" arg2="B"> 0.0 </op></test>
+<test><op name="distance" arg1="B" arg2="A"> 0.0 </op></test>
</case>

<case>
@@ -13,6 +14,31 @@
<a> POINT(10 10) </a>
<b> POINT (10 0) </b>
<test><op name="distance" arg1="A" arg2="B"> 10.0 </op></test>
+<test><op name="distance" arg1="B" arg2="A"> 10.0 </op></test>
+</case>
+
+<case>
+ <desc>PP - point to multipoint</desc>
+ <a> POINT(10 10) </a>
+ <b> MULTIPOINT ((10 0), (30 30)) </b>
+<test><op name="distance" arg1="A" arg2="B"> 10.0 </op></test>
+<test><op name="distance" arg1="B" arg2="A"> 10.0 </op></test>
+</case>
+
+<case>
+ <desc>PP - point to multipoint with empty element</desc>
+ <a> POINT(10 10) </a>
+ <b> MULTIPOINT ((10 0), EMPTY) </b>
+<test><op name="distance" arg1="A" arg2="B"> 10.0 </op></test>
+<test><op name="distance" arg1="B" arg2="A"> 10.0 </op></test>
+</case>
+
+<case>
+ <desc>LL - line to empty line</desc>
+ <a> LINESTRING (0 0, 0 10) </a>
+ <b> LINESTRING EMPTY </b>
+<test><op name="distance" arg1="A" arg2="B"> 0.0 </op></test>
+<test><op name="distance" arg1="B" arg2="A"> 0.0 </op></test>
</case>

<case>
@@ -20,6 +46,31 @@
<a> LINESTRING (0 0, 0 10) </a>
<b> LINESTRING (10 0, 10 10) </b>
<test><op name="distance" arg1="A" arg2="B"> 10.0 </op></test>
+<test><op name="distance" arg1="B" arg2="A"> 10.0 </op></test>
+</case>
+
+<case>
+ <desc>LL - line to multiline</desc>
+ <a> LINESTRING (0 0, 0 10) </a>
+ <b> MULTILINESTRING ((10 0, 10 10), (50 50, 60 60)) </b>
+<test><op name="distance" arg1="A" arg2="B"> 10.0 </op></test>
+<test><op name="distance" arg1="B" arg2="A"> 10.0 </op></test>
+</case>
+
+<case>
+ <desc>LL - line to multiline with empty element</desc>
+ <a> LINESTRING (0 0, 0 10) </a>
+ <b> MULTILINESTRING ((10 0, 10 10), EMPTY) </b>
+<test><op name="distance" arg1="A" arg2="B"> 10.0 </op></test>
+<test><op name="distance" arg1="B" arg2="A"> 10.0 </op></test>
+</case>
+
+<case>
+ <desc>PA - point to empty polygon</desc>
+ <a> POINT (240 160) </a>
+ <b> POLYGON EMPTY </b>
+<test><op name="distance" arg1="A" arg2="B" > 0.0 </op></test>
+<test><op name="distance" arg1="B" arg2="A" > 0.0 </op></test>
</case>

<case>
@@ -27,6 +78,7 @@
<a> POINT (240 160) </a>
<b> POLYGON ((100 260, 340 180, 100 60, 180 160, 100 260)) </b>
<test><op name="distance" arg1="A" arg2="B" > 0.0 </op></test>
+<test><op name="distance" arg1="B" arg2="A" > 0.0 </op></test>
</case>

<case>
@@ -34,6 +86,7 @@
<a> LINESTRING (40 300, 280 220, 60 160, 140 60) </a>
<b> LINESTRING (140 360, 260 280, 240 120, 120 160) </b>
<test><op name="distance" arg1="A" arg2="B" > 0.0 </op></test>
+<test><op name="distance" arg1="B" arg2="A" > 0.0 </op></test>
</case>

<case>
@@ -41,6 +94,7 @@
<a> POLYGON ((60 260, 260 180, 100 60, 60 160, 60 260)) </a>
<b> POLYGON ((220 280, 120 160, 300 60, 360 220, 220 280)) </b>
<test><op name="distance" arg1="A" arg2="B" > 0.0 </op></test>
+<test><op name="distance" arg1="B" arg2="A" > 0.0 </op></test>
</case>

<case>
@@ -48,6 +102,7 @@
<a> POLYGON ((100 320, 60 120, 240 180, 200 260, 100 320)) </a>
<b> POLYGON ((420 320, 280 260, 400 100, 420 320)) </b>
<test><op name="distance" arg1="A" arg2="B" > 71.55417527999327 </op></test>
+<test><op name="distance" arg1="B" arg2="A" > 71.55417527999327 </op></test>
</case>

<case>
@@ -55,13 +110,23 @@
<a> MULTIPOLYGON (((40 240, 160 320, 40 380, 40 240)), ((100 240, 240 60, 40 40, 100 240))) </a>
<b> MULTIPOLYGON (((220 280, 120 160, 300 60, 360 220, 220 280)), ((240 380, 280 300, 420 340, 240 380))) </b>
<test><op name="distance" arg1="A" arg2="B" > 0.0 </op></test>
+<test><op name="distance" arg1="B" arg2="A" > 0.0 </op></test>
</case>

<case>
- <desc>mAmA - multipolygon with empty component</desc>
+ <desc>mAmA - multipolygon with empty element</desc>
<a> MULTIPOLYGON (EMPTY, ((98 200, 200 200, 200 99, 98 99, 98 200))) </a>
<b> POLYGON ((300 200, 400 200, 400 100, 300 100, 300 200)) </b>
<test><op name="distance" arg1="A" arg2="B" > 100.0 </op></test>
+<test><op name="distance" arg1="B" arg2="A" > 100.0 </op></test>
+</case>
+
+<case>
+ <desc>GCGC - geometry collections with mixed dimensions</desc>
+ <a> GEOMETRYCOLLECTION (LINESTRING (10 10, 50 10), POINT (90 10)) </a>
+ <b> GEOMETRYCOLLECTION (POLYGON ((90 20, 60 20, 60 50, 90 50, 90 20)), LINESTRING (10 50, 30 70)) </b>
+<test><op name="distance" arg1="A" arg2="B" > 10.0 </op></test>
+<test><op name="distance" arg1="B" arg2="A" > 10.0 </op></test>
</case>

</run>
Binary file removed deps/vendor/geos-3.11.2.tar.bz2
Binary file not shown.
Binary file added deps/vendor/geos-3.12.0.tar.bz2
Binary file not shown.
1 change: 1 addition & 0 deletions test/data/world-administrative-boundaries.geojson

Large diffs are not rendered by default.

0 comments on commit 8d3e9fd

Please sign in to comment.