[geos-commits] [SCM] GEOS branch main updated. 1bd84740d81df4eec08f82d19e425c7c74cadbf0

git at osgeo.org git at osgeo.org
Sun Nov 1 18:20:28 PST 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  1bd84740d81df4eec08f82d19e425c7c74cadbf0 (commit)
      from  2289bad7aac673a1bffcbbdd96944fcc57405a9c (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 1bd84740d81df4eec08f82d19e425c7c74cadbf0
Author: Daniel Baston <dbaston at gmail.com>
Date:   Sat Oct 31 16:00:34 2026 -0400

    NodableArcString: Handle degenerate arcs with repeated points
    
    Co-authored-by: Alejandro Pacheco <ale at alepacheco.dev>

diff --git a/src/noding/NodableArcString.cpp b/src/noding/NodableArcString.cpp
index 5b41a62f8..7c91634ee 100644
--- a/src/noding/NodableArcString.cpp
+++ b/src/noding/NodableArcString.cpp
@@ -268,7 +268,7 @@ public:
             m_coords = std::make_unique<geom::CoordinateSequence>(0, m_constructZ, m_constructM);
         }
 
-        m_coords->add(seq, pos, pos + 2, false);
+        m_coords->add(seq, pos + !m_coords->isEmpty(), pos + 2, true);
         m_arcs.emplace_back(*m_coords, m_coords->getSize() - 3, center, radius, orientation);
     }
 
diff --git a/tests/unit/capi/GEOSNodeTest.cpp b/tests/unit/capi/GEOSNodeTest.cpp
index 10166adbc..97401d714 100644
--- a/tests/unit/capi/GEOSNodeTest.cpp
+++ b/tests/unit/capi/GEOSNodeTest.cpp
@@ -414,5 +414,28 @@ void object::test<19>()
                                       reinterpret_cast<Geometry*>(expected_), 1e-4);
 }
 
+template<>
+template<>
+void object::test<20>()
+{
+    set_test_name("CircularString with repeated points");
+
+    input_ = fromWKT("MULTICURVE (CIRCULARSTRING (0 0, 0 0, 2 0, 3 1, 4 0), LINESTRING (3 0, 3 2))");
+
+    result_ = GEOSNode(input_);
+    ensure(result_);
+
+    ensure_equals(GEOSGetNumGeometries(result_), 4);
+
+    expected_ = fromWKT("MULTICURVE ("
+                        "CIRCULARSTRING (0 0, 0 0, 2 0, 2.2928932188 0.7071067812, 3 1),"
+                        "CIRCULARSTRING (3 1, 3.7071067812 0.7071067812, 4 0),"
+                        "(3 0, 3 1),"
+                        "(3 1, 3 2))");
+
+    ensure_equals_exact_geometry_xyzm(reinterpret_cast<Geometry*>(result_),
+                                      reinterpret_cast<Geometry*>(expected_), 1e-4);
+}
+
 } // namespace tut
 
diff --git a/tests/unit/noding/NodableArcStringTest.cpp b/tests/unit/noding/NodableArcStringTest.cpp
index c1f1c02ce..31b8b9832 100644
--- a/tests/unit/noding/NodableArcStringTest.cpp
+++ b/tests/unit/noding/NodableArcStringTest.cpp
@@ -12,6 +12,7 @@ using geos::geom::CoordinateXY;
 using geos::geom::CoordinateXYZM;
 using geos::noding::ArcString;
 using geos::noding::NodableArcString;
+using namespace std::string_literals;
 
 namespace tut {
 
@@ -223,4 +224,72 @@ void object::test<5>()
                 });
 }
 
-}
\ No newline at end of file
+template<>
+template<>
+void object::test<6>()
+{
+    set_test_name("getNoded keeps all three points of arcs with repeated points");
+
+    for (const char* wkt : {
+            "CIRCULARSTRING (0 0, 0 0, 0 0)", // 0 == 1 == 2
+            "CIRCULARSTRING (0 0, 0 0, 2 0, 3 1, 4 0)", // 0 == 1
+            "CIRCULARSTRING (0 0, 1 1, 1 1, 3 1, 4 0)", // 1 == 2
+            "CIRCULARSTRING (0 0, 1 1, 2 0, 2 0, 4 0)", // 2 == 3
+            "CIRCULARSTRING (0 0, 1 1, 2 0, 3 1, 3 1)" // 3 == 4
+        }) {
+        const auto g = reader_.read<CircularString>(wkt);
+
+        NodableArcString nas(g->getArcs(), g->getSharedCoordinates(), false, false, nullptr);
+
+        std::vector<std::unique_ptr<ArcString>> noded;
+        nas.getNoded(noded);
+
+        ensure_equals("noded.size(): "s + wkt, noded.size(), 1u);
+        ensure_equals("noded[0]->getSize(): "s + wkt, noded[0]->getSize(), g->getArcs().size());
+        ensure("noded[0]->getCoordinates(): "s + wkt, noded[0]->getCoordinates()->equalsIdentical(*g->getCoordinatesRO()));
+        for (std::size_t i = 0; i < noded[0]->getSize(); i++) {
+            ensure_equals(wkt, noded[0]->getArc(i).getCoordinatePosition(), 2*i);
+        }
+    }
+}
+
+template<>
+template<>
+void object::test<7>()
+{
+    set_test_name("getNoded keeps arc with repeated points before a split arc");
+
+    const auto g = reader_.read<CircularString>("CIRCULARSTRING (0 0, 0 0, 2 0, 3 1, 4 0)");
+
+    NodableArcString nas(g->getArcs(), g->getSharedCoordinates(), false, false, nullptr);
+    nas.addIntersection(CoordinateXY{3, 1}, 1);
+
+    std::vector<std::unique_ptr<ArcString>> noded;
+    nas.getNoded(noded);
+
+    ensure_equals(noded.size(), 2u);
+
+    const auto& seq = *noded[0]->getCoordinates();
+    ensure_equals(noded[0]->getSize(), 2u);
+    ensure_equals(seq.size(), 5u);
+
+    const CircularArc& arc0 = noded[0]->getArc(0);
+    ensure_equals(arc0.getCoordinatePosition(), 0u);
+    ensure_equals(arc0.p0(), XY{0, 0});
+    ensure_equals(arc0.p1(), XY{0, 0});
+    ensure_equals(arc0.p2(), XY{2, 0});
+
+    const CircularArc& arc1 = noded[0]->getArc(1);
+    ensure_equals(arc1.getCoordinatePosition(), 2u);
+    ensure_equals(arc1.p0(), XY{2, 0});
+    ensure_equals(arc1.p2(), XY{3, 1});
+
+    ensure_equals(noded[1]->getSize(), 1u);
+    ensure_equals(noded[1]->getCoordinates()->size(), 3u);
+
+    const CircularArc& arc2 = noded[1]->getArc(0);
+    ensure_arc_equals(arc2, CircularArc::create(XY{3, 1}, XY{4, 0}, XY{3, 0}, 1, Orientation::CLOCKWISE), 1e-8);
+    ensure_equals(arc2.p2(), XY{4, 0});
+}
+
+} // namespace tut

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

Summary of changes:
 src/noding/NodableArcString.cpp            |  2 +-
 tests/unit/capi/GEOSNodeTest.cpp           | 23 ++++++++++
 tests/unit/noding/NodableArcStringTest.cpp | 71 +++++++++++++++++++++++++++++-
 3 files changed, 94 insertions(+), 2 deletions(-)


hooks/post-receive
-- 
GEOS


More information about the geos-commits mailing list