[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