[geos-commits] [SCM] GEOS branch 3.12 updated. efe590e6c49a25f5fe10aca2eab2e12a79d64f0a

git at osgeo.org git at osgeo.org
Mon Sep 18 19:10:41 PDT 2023


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, 3.12 has been updated
       via  efe590e6c49a25f5fe10aca2eab2e12a79d64f0a (commit)
       via  8ff902126e214338b74648e04135a5e2bd8f4648 (commit)
       via  e8949f3076577771582286f10e51f4dd210e9853 (commit)
      from  9136cb0593408e3a90625283613301faf11409fc (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 efe590e6c49a25f5fe10aca2eab2e12a79d64f0a
Author: Martin Davis <mtnclimb at gmail.com>
Date:   Mon Sep 18 19:09:22 2023 -0700

    Remove debug prints

diff --git a/src/operation/distance/IndexedFacetDistance.cpp b/src/operation/distance/IndexedFacetDistance.cpp
index 8866b0d1e..d49012088 100644
--- a/src/operation/distance/IndexedFacetDistance.cpp
+++ b/src/operation/distance/IndexedFacetDistance.cpp
@@ -66,19 +66,17 @@ IndexedFacetDistance::isWithinDistance(const Geometry* g, double maxDistance) co
     if (envDist > maxDistance) {
         return false;
     }
-//*
+
     //-- heuristic: for atomic indexed geom, test distance to envelope of test geom
     if (baseGeometry.getNumGeometries() == 1
         && ! g->getEnvelopeInternal()->contains(baseGeometry.getEnvelopeInternal()))
     {
         auto env2 = g->getEnvelope();
-std::cout << "env dist = " << distance(env2.get()) << std::endl;
         if (distance(env2.get()) > maxDistance) {
-std::cout << "env dist > maxdistance of " << maxDistance << std::endl;
             return false;
         }
     }
-//*/
+
     auto tree2 = FacetSequenceTreeBuilder::build(g);
     return cachedTree->isWithinDistance<FacetDistance>(*tree2, maxDistance);
 }
diff --git a/tests/unit/operation/distance/IndexedFacetDistanceTest.cpp b/tests/unit/operation/distance/IndexedFacetDistanceTest.cpp
index a08eb9887..5b6f0cb73 100644
--- a/tests/unit/operation/distance/IndexedFacetDistanceTest.cpp
+++ b/tests/unit/operation/distance/IndexedFacetDistanceTest.cpp
@@ -88,7 +88,6 @@ struct test_facetdistanceop_data {
 
         IndexedFacetDistance ifd(g1.get());
         bool result = ifd.isWithinDistance(g2.get(), distance);
-std::cout << "result = " << result << "  expected = " << expected << std::endl;
         ensure_equals(result, expected);
     }
 

commit 8ff902126e214338b74648e04135a5e2bd8f4648
Author: Martin Davis <mtnclimb at gmail.com>
Date:   Mon Sep 18 19:03:40 2023 -0700

    Update NEWS

diff --git a/NEWS.md b/NEWS.md
index 3da4df688..cce2cdc68 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -6,6 +6,8 @@
   - Remove undefined behaviour in use of null PrecisionModel (GH-931, Jeff Walton)
   - Explicitly set endianness for some tests so that output matches expected (GH-934, Paul Ramsey)
   - Fix IncrementalDelaunayTriangulator to ensure triangulation boundary is convex (GH-953, Martin Davis)
+  - Fix PreparedLineStringDistance for lines within envelope and polygons (GH-959, Martin Davis) 
+
 
 
 

commit e8949f3076577771582286f10e51f4dd210e9853
Author: Martin Davis <mtnclimb at gmail.com>
Date:   Mon Sep 18 18:59:58 2023 -0700

    Fix PreparedLineStringDistance for lines within envelope and polygons (#959)

diff --git a/src/geom/prep/PreparedLineStringDistance.cpp b/src/geom/prep/PreparedLineStringDistance.cpp
index 9e7c5c705..5bb2b4523 100644
--- a/src/geom/prep/PreparedLineStringDistance.cpp
+++ b/src/geom/prep/PreparedLineStringDistance.cpp
@@ -32,12 +32,19 @@ PreparedLineStringDistance::distance(const geom::Geometry* g) const
         return DoubleInfinity;
     }
 
-    // TODO: test if this shortcut be any useful
-    //if ( prepLine.intersects(g) ) return 0.0;
-
-    /* Not intersecting, compute distance from facets */
+    /* Compute potential distance from facets */
     operation::distance::IndexedFacetDistance *idf = prepLine.getIndexedFacetDistance();
-    return idf->distance(g);
+    double dist = idf->distance(g);
+    if (dist == 0.0)
+        return 0.0;
+
+    // If any point from prepLine is contained by g, the distance is zero
+    // Do this last because this PIP test is not indexed.
+    if ( g->getDimension() == 2 
+            && prepLine.isAnyTargetComponentInTest(g)) {
+        return 0.0;
+    }
+    return dist;
 }
 
 bool
@@ -49,7 +56,15 @@ PreparedLineStringDistance::isWithinDistance(const geom::Geometry* g, double d)
     }
 
     operation::distance::IndexedFacetDistance *idf = prepLine.getIndexedFacetDistance();
-    return idf->isWithinDistance(g, d);
+    if (idf->isWithinDistance(g, d))
+        return true;
+
+    // If any point from prepLine is contained by g, the distance is zero
+    // Do this last because this PIP test is not indexed.
+    if ( g->getDimension() == 2 ) {
+        return prepLine.isAnyTargetComponentInTest(g);
+    }
+    return false;
 }
 
 
diff --git a/src/operation/distance/IndexedFacetDistance.cpp b/src/operation/distance/IndexedFacetDistance.cpp
index 1d16c4146..8866b0d1e 100644
--- a/src/operation/distance/IndexedFacetDistance.cpp
+++ b/src/operation/distance/IndexedFacetDistance.cpp
@@ -59,17 +59,26 @@ IndexedFacetDistance::distance(const Geometry* g) const
 bool
 IndexedFacetDistance::isWithinDistance(const Geometry* g, double maxDistance) const
 {
+    std::cout << "geom dist = " << distance(g) << std::endl;
+
     // short-circuit check
     double envDist = baseGeometry.getEnvelopeInternal()->distance(*g->getEnvelopeInternal());
     if (envDist > maxDistance) {
         return false;
     }
-
-    auto env2 = g->getEnvelope();
-    if (distance(env2.get()) > maxDistance) {
-        return false;
+//*
+    //-- heuristic: for atomic indexed geom, test distance to envelope of test geom
+    if (baseGeometry.getNumGeometries() == 1
+        && ! g->getEnvelopeInternal()->contains(baseGeometry.getEnvelopeInternal()))
+    {
+        auto env2 = g->getEnvelope();
+std::cout << "env dist = " << distance(env2.get()) << std::endl;
+        if (distance(env2.get()) > maxDistance) {
+std::cout << "env dist > maxdistance of " << maxDistance << std::endl;
+            return false;
+        }
     }
-
+//*/
     auto tree2 = FacetSequenceTreeBuilder::build(g);
     return cachedTree->isWithinDistance<FacetDistance>(*tree2, maxDistance);
 }
diff --git a/tests/unit/capi/GEOSPreparedDistanceTest.cpp b/tests/unit/capi/GEOSPreparedDistanceTest.cpp
index 3d1369cb8..45147eec2 100644
--- a/tests/unit/capi/GEOSPreparedDistanceTest.cpp
+++ b/tests/unit/capi/GEOSPreparedDistanceTest.cpp
@@ -178,5 +178,44 @@ void object::test<9>
     );
 }
 
+// Prepared line within envelope of test line
+template<>
+template<>
+void object::test<12>
+()
+{
+    checkDistance(
+        "LINESTRING (1 4, 4 7)",
+        "LINESTRING (1 1, 5 5, 5 9)",
+        1
+    );
+}
+
+// Prepared line within polygon
+template<>
+template<>
+void object::test<13>
+()
+{
+    checkDistance(
+        "LINESTRING (30 30, 70 70)",
+        "POLYGON ((0 100, 100 100, 100 0, 0 0, 0 100))",
+        0
+    );
+}
+
+// Prepared multiline with one element within polygon
+template<>
+template<>
+void object::test<14>
+()
+{
+    checkDistance(
+        "MULTILINESTRING ((30 30, 70 70), (170 200, 200 170))",
+        "POLYGON ((0 100, 100 100, 100 0, 0 0, 0 100))",
+        0
+    );
+}
+
 } // namespace tut
 
diff --git a/tests/unit/capi/GEOSPreparedDistanceWithinTest.cpp b/tests/unit/capi/GEOSPreparedDistanceWithinTest.cpp
index 3cd9bd336..81e74491b 100644
--- a/tests/unit/capi/GEOSPreparedDistanceWithinTest.cpp
+++ b/tests/unit/capi/GEOSPreparedDistanceWithinTest.cpp
@@ -1,5 +1,5 @@
 //
-// Test Suite for C-API GEOSPreparedDistance
+// Test Suite for C-API GEOSPreparedDistanceWithin
 
 #include <tut/tut.hpp>
 // geos
@@ -213,5 +213,76 @@ void object::test<11>
     );
 }
 
+// Prepared line within envelope of test line
+// see https://github.com/libgeos/geos/issues/958
+template<>
+template<>
+void object::test<12>
+()
+{
+    checkDistanceWithin(
+        "LINESTRING (2 2, 3 3, 4 4, 5 5, 6 6, 7 7)",
+        "LINESTRING (0 0, 1 1, 2 2, 3 3, 4 4, 5 5, 6 6, 7 7, 8 8, 9 9)",
+        1,
+        1
+    );
+}
+
+// Prepared line within test geometry
+// see https://github.com/libgeos/geos/issues/960
+template<>
+template<>
+void object::test<13>
+()
+{
+    checkDistanceWithin(
+        "LINESTRING (30 30, 70 70)",
+        "POLYGON ((0 100, 100 100, 100 0, 0 0, 0 100))",
+        1,
+        1
+    );
+}
+
+// Prepared multiline with one element within Polygon
+template<>
+template<>
+void object::test<14>
+()
+{
+    checkDistanceWithin(
+        "MULTILINESTRING ((30 30, 70 70), (170 200, 200 170))",
+        "POLYGON ((0 100, 100 100, 100 0, 0 0, 0 100))",
+        1,
+        1
+    );
+}
+
+// Prepared multiline with one element within MultiPolygon.
+template<>
+template<>
+void object::test<15>
+()
+{
+    checkDistanceWithin(
+        "MULTILINESTRING ((1 6, 1 1), (15 16, 15 14))",
+        "MULTIPOLYGON (((10 20, 20 20, 20 10, 10 10, 10 20)), ((30 20, 40 20, 40 10, 30 10, 30 20)))",
+        1,
+        1
+    );
+}
+
+// Indexed multiline with one element within line envelope.
+template<>
+template<>
+void object::test<16>()
+{
+    checkDistanceWithin(
+        "MULTILINESTRING ((1 6, 1 1), (11 14, 11 11))",
+        "LINESTRING (10 10, 10 20, 30 20)",
+        2,
+        1
+    );
+}
+
 } // namespace tut
 
diff --git a/tests/unit/operation/distance/IndexedFacetDistanceTest.cpp b/tests/unit/operation/distance/IndexedFacetDistanceTest.cpp
index c4e8210a4..a08eb9887 100644
--- a/tests/unit/operation/distance/IndexedFacetDistanceTest.cpp
+++ b/tests/unit/operation/distance/IndexedFacetDistanceTest.cpp
@@ -12,6 +12,7 @@
 // tut
 #include <tut/tut.hpp>
 #include <tut/tut_macros.hpp>
+#include <utility.h>
 // geos
 #include <geos/profiler.h>
 #include <geos/constants.h>
@@ -33,6 +34,7 @@
 #endif
 
 using geos::operation::distance::IndexedFacetDistance;
+using geos::geom::Coordinate;
 
 namespace tut {
 //
@@ -59,19 +61,35 @@ struct test_facetdistanceop_data {
     {}
 
     void
-    checkDistanceNearestPoints(std::string wkt1, std::string wkt2, double distance,
-                               geos::geom::Coordinate& p1, geos::geom::Coordinate& p2)
+    checkDistanceNearestPoints(std::string wkt1, std::string wkt2, double distanceExpected,
+                               const geos::geom::Coordinate& p1, 
+                               const geos::geom::Coordinate& p2)
     {
         using geos::operation::distance::IndexedFacetDistance;
         GeomPtr g1(_wktreader.read(wkt1));
         GeomPtr g2(_wktreader.read(wkt2));
         auto pts = IndexedFacetDistance::nearestPoints(g1.get(), g2.get());
-        ensure(fabs((*pts)[0].distance((*pts)[1])-distance) < 1e08);
-        ensure(fabs((*pts)[0].x - p1.x) < 1e-08);
-        ensure(fabs((*pts)[0].y - p1.y) < 1e-08);
-        ensure(fabs((*pts)[1].x - p2.x) < 1e-08);
-        ensure(fabs((*pts)[1].y - p2.y) < 1e-08);
-        return;
+        const Coordinate p1Actual = (*pts)[0];
+        const Coordinate p2Actual = (*pts)[1];
+        double distResult = (*pts)[0].distance((*pts)[1]);
+
+        ensure_equals("Distance", distResult, distanceExpected, 1e-4);
+        ensure_equals_xy(p1Actual, p1, 1e-08);
+        ensure_equals_xy(p2Actual, p2, 1e-08);
+    }
+
+    void
+    checkWithinDistance(std::string wkt1, std::string wkt2, double distance,
+                               bool expected)
+    {
+        using geos::operation::distance::IndexedFacetDistance;
+        std::unique_ptr<geos::geom::Geometry> g1(_wktreader.read(wkt1));
+        std::unique_ptr<geos::geom::Geometry> g2(_wktreader.read(wkt2));
+
+        IndexedFacetDistance ifd(g1.get());
+        bool result = ifd.isWithinDistance(g2.get(), distance);
+std::cout << "result = " << result << "  expected = " << expected << std::endl;
+        ensure_equals(result, expected);
     }
 
     int
@@ -104,8 +122,6 @@ struct test_facetdistanceop_data {
         return ls;
     }
 
-
-
 };
 
 typedef test_group<test_facetdistanceop_data> group;
@@ -408,6 +424,57 @@ void object::test<12>()
 }
 
 
+// Indexed multiline with one element within line envelope.
+template<>
+template<>
+void object::test<13>()
+{
+    checkWithinDistance(
+        "MULTILINESTRING ((1 6, 1 1), (11 14, 11 11))",
+        "LINESTRING (10 10, 10 20, 30 20)",
+        2,
+        true
+    );
+}
+
+// Indexed multiline with one element within multiline envelope and close to inner line.
+template<>
+template<>
+void object::test<14>()
+{
+    checkWithinDistance(
+        "MULTILINESTRING ((1 6, 1 1), (16 16, 19 13))",
+        "MULTILINESTRING ((10 10, 10 20, 30 20), (20 13, 20 16))",
+        2,
+        true
+    );
+}
+
+// Indexed multiline with one element within line envelope.
+template<>
+template<>
+void object::test<15>
+()
+{
+    checkDistanceNearestPoints(
+        "MULTILINESTRING ((1 6, 1 1), (11 15, 13 17))", 
+        "LINESTRING (10 10, 10 20, 30 20)", 
+        1, Coordinate{11, 15}, Coordinate{10, 15}
+    );
+}
+
+// Indexed multiline with one element within line envelope.
+template<>
+template<>
+void object::test<16>
+()
+{
+    checkDistanceNearestPoints(
+        "MULTILINESTRING ((6 6, 7 7), (100 100, 101 101))", 
+        "LINESTRING (0 10, 10 0)", 
+        1.41421, Coordinate{6, 6}, Coordinate{5, 5}
+    );
+}
 
 // TODO: finish the tests by adding:
 // 	LINESTRING - *all*
diff --git a/tests/unit/utility.h b/tests/unit/utility.h
index fe6d7e9db..9df558fc0 100644
--- a/tests/unit/utility.h
+++ b/tests/unit/utility.h
@@ -96,6 +96,23 @@ instanceOf(InstanceType const* instance)
     return dynamic_cast<Type const*>(instance);
 }
 
+inline void
+ensure_equals_xy(geos::geom::Coordinate const& actual,
+                  geos::geom::Coordinate const& expected)
+{
+    ensure_equals("Coordinate X", actual.x, expected.x );
+    ensure_equals("Coordinate Y", actual.y, expected.y );
+}
+
+inline void
+ensure_equals_xy(geos::geom::Coordinate const& actual,
+                  geos::geom::Coordinate const& expected,
+                  double tol)
+{
+    ensure_equals("Coordinate X", actual.x, expected.x, tol );
+    ensure_equals("Coordinate Y", actual.y, expected.y, tol );
+}
+
 inline void
 ensure_equals_xyz(geos::geom::Coordinate const& actual,
                   geos::geom::Coordinate const& expected)

-----------------------------------------------------------------------

Summary of changes:
 NEWS.md                                            |  2 +
 src/geom/prep/PreparedLineStringDistance.cpp       | 27 +++++--
 src/operation/distance/IndexedFacetDistance.cpp    | 13 +++-
 tests/unit/capi/GEOSPreparedDistanceTest.cpp       | 39 ++++++++++
 tests/unit/capi/GEOSPreparedDistanceWithinTest.cpp | 73 +++++++++++++++++-
 .../distance/IndexedFacetDistanceTest.cpp          | 86 +++++++++++++++++++---
 tests/unit/utility.h                               | 17 +++++
 7 files changed, 237 insertions(+), 20 deletions(-)


hooks/post-receive
-- 
GEOS


More information about the geos-commits mailing list