-
Notifications
You must be signed in to change notification settings - Fork 43
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
277 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 not shown.
Binary file not shown.
Large diffs are not rendered by default.
Oops, something went wrong.