[geos-commits] [SCM] GEOS branch main updated. 861ed20b38bb26067f5a552302b30d3637c03bdf

git at osgeo.org git at osgeo.org
Tue Mar 24 10:42:42 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  861ed20b38bb26067f5a552302b30d3637c03bdf (commit)
      from  5e4f5981551ec79836ac25bda4fce0b707187fc0 (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 861ed20b38bb26067f5a552302b30d3637c03bdf
Author: Daniel Baston <dbaston at gmail.com>
Date:   Tue Mar 24 13:42:22 2026 -0400

    LineLimiter: Avoid dropping M values (#1408)

diff --git a/include/geos/operation/overlayng/EdgeNodingBuilder.h b/include/geos/operation/overlayng/EdgeNodingBuilder.h
index cae8a44e7..0927241ba 100644
--- a/include/geos/operation/overlayng/EdgeNodingBuilder.h
+++ b/include/geos/operation/overlayng/EdgeNodingBuilder.h
@@ -140,7 +140,7 @@ private:
     * limit the line to the clip envelope.
     *
     */
-    std::vector<std::unique_ptr<CoordinateSequence>>& limit(const LineString* line);
+    std::vector<std::unique_ptr<CoordinateSequence>>& limit(const LineString* line) const;
 
     /**
     * If a clipper is present,
diff --git a/include/geos/operation/overlayng/LineLimiter.h b/include/geos/operation/overlayng/LineLimiter.h
index 8a9b27f49..91f00eeec 100644
--- a/include/geos/operation/overlayng/LineLimiter.h
+++ b/include/geos/operation/overlayng/LineLimiter.h
@@ -54,6 +54,7 @@ namespace overlayng { // geos.operation.overlayng
 class GEOS_DLL LineLimiter {
     using Envelope = geos::geom::Envelope;
     using Coordinate = geos::geom::Coordinate;
+    using CoordinateXY = geos::geom::CoordinateXY;
     using CoordinateSequence = geos::geom::CoordinateSequence;
 
 private:
@@ -61,14 +62,21 @@ private:
     // Members
     const Envelope* limitEnv;
     std::unique_ptr<geom::CoordinateSequence> ptList;
-    const Coordinate* lastOutside;
+    const CoordinateXY* lastOutside;
     std::vector<std::unique_ptr<CoordinateSequence>> sections;
+    bool hasZ{false};
+    bool hasM{false};
 
     // Methods
-    void addPoint(const Coordinate* p);
-    void addOutside(const Coordinate* p);
-    bool isLastSegmentIntersecting(const Coordinate* p);
-    bool isSectionOpen();
+    template<typename CoordType>
+    void addPoint(const CoordType& p);
+
+    template<typename CoordType>
+    void addOutside(const CoordType& p);
+    bool isLastSegmentIntersecting(const CoordinateXY& p) const;
+    bool isSectionOpen() const;
+
+    template<typename CoordType>
     void startSection();
     void finishSection();
 
diff --git a/src/operation/overlayng/EdgeNodingBuilder.cpp b/src/operation/overlayng/EdgeNodingBuilder.cpp
index d63f4acb3..b063770f1 100644
--- a/src/operation/overlayng/EdgeNodingBuilder.cpp
+++ b/src/operation/overlayng/EdgeNodingBuilder.cpp
@@ -414,7 +414,7 @@ EdgeNodingBuilder::isToBeLimited(const LineString* line) const
 
 /*private*/
 std::vector<std::unique_ptr<CoordinateSequence>>&
-EdgeNodingBuilder::limit(const LineString* line)
+EdgeNodingBuilder::limit(const LineString* line) const
 {
     const CoordinateSequence* pts = line->getCoordinatesRO();
     return limiter->limit(pts);
diff --git a/src/operation/overlayng/LineLimiter.cpp b/src/operation/overlayng/LineLimiter.cpp
index 57036e248..f1410f424 100644
--- a/src/operation/overlayng/LineLimiter.cpp
+++ b/src/operation/overlayng/LineLimiter.cpp
@@ -34,32 +34,36 @@ LineLimiter::limit(const CoordinateSequence *pts)
     lastOutside = nullptr;
     ptList.reset(nullptr);
     sections.clear();
+    hasZ = pts->hasZ();
+    hasM = pts->hasM();
 
-    for (std::size_t i = 0; i < pts->size(); i++) {
-        const Coordinate* p = &(pts->getAt(i));
-        if (limitEnv->intersects(*p)) {
+    pts->forEach([this](const auto& p) {
+        if (limitEnv->intersects(p)) {
             addPoint(p);
         }
         else {
             addOutside(p);
         }
-    }
+    });
+
     // finish last section, if any
     finishSection();
     return sections;
 }
 
 /*private*/
+template<typename CoordType>
 void
-LineLimiter::addPoint(const Coordinate* p)
+LineLimiter::addPoint(const CoordType& p)
 {
-    startSection();
-    ptList->add(*p, false);
+    startSection<CoordType>();
+    ptList->add(p, false);
 }
 
 /*private*/
+template<typename CoordType>
 void
-LineLimiter::addOutside(const Coordinate* p)
+LineLimiter::addOutside(const CoordType& p)
 {
     bool segIntersects = isLastSegmentIntersecting(p);
     if (!segIntersects) {
@@ -67,16 +71,16 @@ LineLimiter::addOutside(const Coordinate* p)
     }
     else {
         if(lastOutside != nullptr) {
-            addPoint(lastOutside);
+            addPoint(*static_cast<const CoordType*>(lastOutside));
         }
         addPoint(p);
     }
-    lastOutside = p;
+    lastOutside = &p;
 }
 
 /*private*/
 bool
-LineLimiter::isLastSegmentIntersecting(const Coordinate* p)
+LineLimiter::isLastSegmentIntersecting(const CoordinateXY& p) const
 {
     if (lastOutside == nullptr) {
         // last point must have been inside
@@ -84,26 +88,27 @@ LineLimiter::isLastSegmentIntersecting(const Coordinate* p)
             return true;
         return false;
     }
-    return limitEnv->intersects(*lastOutside, *p);
+    return limitEnv->intersects(*lastOutside, p);
 }
 
 /*private*/
 bool
-LineLimiter::isSectionOpen()
+LineLimiter::isSectionOpen() const
 {
     return ptList != nullptr;
 }
 
 /*private*/
+template<typename CoordType>
 void
 LineLimiter::startSection()
 {
     if (!isSectionOpen()) {
-        ptList = detail::make_unique<CoordinateSequence>();
+        ptList = std::make_unique<CoordinateSequence>(0, hasZ, hasM);
     }
 
     if (lastOutside != nullptr) {
-        ptList->add(*lastOutside, false);
+        ptList->add(*static_cast<const CoordType*>(lastOutside), false);
     }
     lastOutside = nullptr;
 }
@@ -125,7 +130,7 @@ LineLimiter::finishSection()
     assert(!ptList->hasRepeatedPoints());
     //ptList->erase(std::unique(ptList->begin(), ptList->end()), ptList->end());
 
-    sections.emplace_back(ptList.release());
+    sections.push_back(std::move(ptList));
     ptList.reset(nullptr);
 }
 
diff --git a/tests/unit/operation/overlayng/LineLimiterTest.cpp b/tests/unit/operation/overlayng/LineLimiterTest.cpp
index 025200b97..af9ef9334 100644
--- a/tests/unit/operation/overlayng/LineLimiterTest.cpp
+++ b/tests/unit/operation/overlayng/LineLimiterTest.cpp
@@ -49,7 +49,7 @@ struct test_linelimiter_data {
         // std::cout << "--expect--" << std::endl;
         // std::cout << w.write(expected.get()) << std::endl;
 
-        ensure_equals_geometry(expected.get(), result.get());
+        ensure_equals_geometry_xyzm(expected.get(), result.get());
     }
 
     std::unique_ptr<Geometry>
@@ -170,7 +170,17 @@ void object::test<8> ()
     checkLimit(wkt, env, expected);
 }
 
+template<>
+template<>
+void object::test<9>()
+{
+    set_test_name("M values preserved");
 
+    std::string wkt= "LINESTRING M (7 17 1, 23 17 2, 23 13 3, 7 13 4)";
+    Envelope env(10,20,10,20);
+    std::string expected = "MULTILINESTRING M ((7 17 1, 23 17 2), (23 13 3, 7 13 4))";
+    checkLimit(wkt, env, expected);
+}
 
 
 } // namespace tut
diff --git a/tests/unit/operation/overlayng/OverlayNGZTest.cpp b/tests/unit/operation/overlayng/OverlayNGZTest.cpp
index 732d7eb25..d8625d3cb 100644
--- a/tests/unit/operation/overlayng/OverlayNGZTest.cpp
+++ b/tests/unit/operation/overlayng/OverlayNGZTest.cpp
@@ -326,4 +326,16 @@ void object::test<22> ()
         "POLYGON M ((2 6 7, 3 9 3.875, 9 9 2, 9 5 5.5, 7 6 8, 2 6 7))");
 }
 
+template<>
+template<>
+void object::test<23> ()
+{
+    set_test_name("LINESTRING XYM / LINESTRING XYM intersection");
+
+    // inputs need > 20 vertices to activate LineLimiter
+    checkIntersection("LINESTRING M (4 12 6,3.5 10.5 6.2,3 9 6.5,2.5 7.5 6.8,2 6 7,3.7 6 7.3,5.3 6 7.7,7 6 8,8.3 5.3 8.3,9.7 4.7 8.7,11 4 9,11.7 5.8 9.2,12.3 7.7 9.3,13 9.5 9.5,13.7 11.3 9.7,14.3 13.2 9.8,15 15 10,13.2 14.5 9.3,11.3 14 8.7,9.5 13.5 8,7.7 13 7.3,5.8 12.5 6.7,4 12 6)",
+        "LINESTRING M (1 9 1,2.3 9 1.2,3.7 9 1.3,5 9 1.5,6.3 9 1.7,7.7 9 1.8,9 9 2,9 7.7 2.2,9 6.3 2.3,9 5 2.5,9 3.7 2.7,9 2.3 2.8,9 1 3,7.7 1 3.2,6.3 1 3.3,5 1 3.5,3.7 1 3.7,2.3 1 3.8,1 1 4,1 2.3 3.5,1 3.7 3,1 5 2.5,1 6.3 2,1 7.7 1.5,1 9 1)",
+        "MULTIPOINT M ((3 9 6.5), (9 5 2.5))");
+}
+
 } // namespace tut

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

Summary of changes:
 .../geos/operation/overlayng/EdgeNodingBuilder.h   |  2 +-
 include/geos/operation/overlayng/LineLimiter.h     | 18 ++++++++---
 src/operation/overlayng/EdgeNodingBuilder.cpp      |  2 +-
 src/operation/overlayng/LineLimiter.cpp            | 37 ++++++++++++----------
 tests/unit/operation/overlayng/LineLimiterTest.cpp | 12 ++++++-
 tests/unit/operation/overlayng/OverlayNGZTest.cpp  | 12 +++++++
 6 files changed, 59 insertions(+), 24 deletions(-)


hooks/post-receive
-- 
GEOS


More information about the geos-commits mailing list