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

git at osgeo.org git at osgeo.org
Mon Jul 13 06:30:02 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  1d559c659e0862d5e4ff738391a9258d048d68b9 (commit)
       via  2bc8cca93c7088e57dbb7a73a5269d528b8fad1b (commit)
       via  a4e97f3c1ebd9b7e746c1ec0f98d686b39a8ed43 (commit)
       via  92b27f72feeda5a27e3747abfda79c071a1fb4d4 (commit)
       via  7f1c5dca809b3dc4b6336ab3474011a1a57dd2ba (commit)
      from  c6e5ea1bee84a255495413887e8db4b7ab7d323d (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 1d559c659e0862d5e4ff738391a9258d048d68b9
Author: Daniel Baston <dbaston at gmail.com>
Date:   Fri Jul 10 15:30:42 2026 -0400

    NodableArcString: add unit test

diff --git a/src/noding/NodableArcString.cpp b/src/noding/NodableArcString.cpp
index 810258922..6db428795 100644
--- a/src/noding/NodableArcString.cpp
+++ b/src/noding/NodableArcString.cpp
@@ -287,7 +287,7 @@ NodableArcString::getNoded(std::vector<std::unique_ptr<ArcString>>& splitArcs) {
 
     for (size_t arcIndex = 0; arcIndex < m_arcs.size(); arcIndex++) {
 #if DEBUG_NODABLE_ARC_STRING
-        std::cout << "arc " << arcIndex + 1 << " / " << m_arcs.size();
+        std::cout << "arc " << arcIndex + 1 << " / " << m_arcs.size() << std::endl;
 #endif
         const CircularArc& toSplit = m_arcs[arcIndex];
         const geom::CoordinateXY& center = toSplit.getCenter();
diff --git a/tests/unit/noding/NodableArcStringTest.cpp b/tests/unit/noding/NodableArcStringTest.cpp
index 4bdedad95..c1f1c02ce 100644
--- a/tests/unit/noding/NodableArcStringTest.cpp
+++ b/tests/unit/noding/NodableArcStringTest.cpp
@@ -1,11 +1,13 @@
 #include <tut/tut.hpp>
 #include "utility.h"
 
+#include <geos/geom/CircularString.h>
 #include <geos/noding/NodableArcString.h>
 
 using geos::algorithm::Orientation;
 using geos::geom::CircularArc;
 using geos::geom::Ordinate;
+using geos::geom::CircularString;
 using geos::geom::CoordinateXY;
 using geos::geom::CoordinateXYZM;
 using geos::noding::ArcString;
@@ -58,9 +60,29 @@ struct test_nodablearcstring_data {
         }
     }
 
+    void checkSplit(const std::string& wkt, const CoordinateXY& splitPt, std::size_t pathIndex, const std::vector<std::string>& expected_wkt)
+    {
+        const auto g = reader_.read<CircularString>(wkt);
+        const auto& gfact = *g->getFactory();
+
+        NodableArcString nas(g->getArcs(), g->getSharedCoordinates(), false, false, nullptr);
+        nas.addIntersection(splitPt, pathIndex);
+
+        std::vector<std::unique_ptr<ArcString>> noded;
+        nas.getNoded(noded);
+        ensure_equals(noded.size(), expected_wkt.size());
+
+        for (std::size_t i = 0; i < noded.size(); i++) {
+            std::unique_ptr<Geometry> actual = gfact.createCircularString(noded[i]->getCoordinates());
+            std::unique_ptr<Geometry> expected = reader_.read(expected_wkt[i]);
+        }
+    }
+
     static void ensure_arc_equals(const CircularArc& actual, const CircularArc& expected, double tol) {
         ensure(actual.toString() + " does not equal expected " + expected.toString() ,actual.equals(expected, tol));
     }
+
+    geos::io::WKTReader reader_;
 };
 
 typedef test_group<test_nodablearcstring_data> group;
@@ -170,4 +192,35 @@ void object::test<4>()
     ensure_equals(arc1.p1<CoordinateXYZM>().m, (intPt.m + p2.m) / 2);
 }
 
+template<>
+template<>
+void object::test<5>()
+{
+    set_test_name("splits at arc endpoints");
+
+    checkSplit("CIRCULARSTRING (100 0, 50 50, 0 0, -50 50, 0 100, 50 80, 100 100, 150 50, 100 0)",
+                {0, 0}, 0, {
+                 "CIRCULARSTRING (100 0, 50 50, 0 0)",
+                 "CIRCULARSTRING (0 0, -50 50, 0 100, 50 80, 100 100, 150 50, 100 0)"
+                });
+
+    checkSplit("CIRCULARSTRING (100 0, 50 50, 0 0, -50 50, 0 100, 50 80, 100 100, 150 50, 100 0)",
+                {0, 0}, 1, {
+                 "CIRCULARSTRING (100 0, 50 50, 0 0)",
+                 "CIRCULARSTRING (0 0, -50 50, 0 100, 50 80, 100 100, 150 50, 100 0)"
+                });
+
+    checkSplit("CIRCULARSTRING (100 0, 50 50, 0 0, -50 50, 0 100, 50 80, 100 100, 150 50, 100 0)",
+                {100, 100}, 2, {
+                 "CIRCULARSTRING (100 0, 50 50, 0 0)",
+                 "CIRCULARSTRING (0 0, -50 50, 0 100, 50 80, 100 100, 150 50, 100 0)"
+                });
+
+    checkSplit("CIRCULARSTRING (100 0, 50 50, 0 0, -50 50, 0 100, 50 80, 100 100, 150 50, 100 0)",
+                {100, 100}, 3, {
+                 "CIRCULARSTRING (100 0, 50 50, 0 0)",
+                 "CIRCULARSTRING (0 0, -50 50, 0 100, 50 80, 100 100, 150 50, 100 0)"
+                });
+}
+
 }
\ No newline at end of file

commit 2bc8cca93c7088e57dbb7a73a5269d528b8fad1b
Author: Daniel Baston <dbaston at gmail.com>
Date:   Fri Jul 10 14:16:54 2026 -0400

    XMLTester: Use equalsExact for curve overlay result testing

diff --git a/tests/xmltester/XMLTester.cpp b/tests/xmltester/XMLTester.cpp
index e285ec4d9..3e4aac3a0 100644
--- a/tests/xmltester/XMLTester.cpp
+++ b/tests/xmltester/XMLTester.cpp
@@ -846,11 +846,17 @@ Test::areaDelta(const geom::Geometry* a, const geom::Geometry* b, std::string& r
 void
 Test::checkResult( const Geometry& result )
 {
-    checkResult( result,
-    [](Geometry& expected, Geometry& actual) -> bool {
-        //TODO: change to equalsExact, since compareTo doesn't check empty type
-        return expected.compareTo(&actual) == 0;
-    });
+    if (result.hasCurvedComponents()) {
+        checkResult(result, [](Geometry& expected, Geometry& actual) -> bool {
+            return checkOverlaySuccess(expected, actual);
+        });
+    } else {
+        checkResult( result,
+        [](Geometry& expected, Geometry& actual) -> bool {
+            //TODO: change to equalsExact, since compareTo doesn't check empty type
+            return expected.compareTo(&actual) == 0;
+        });
+    }
 }
 
 void

commit a4e97f3c1ebd9b7e746c1ec0f98d686b39a8ed43
Author: Daniel Baston <dbaston at gmail.com>
Date:   Fri Jul 10 12:42:14 2026 -0400

    NodableArcString: Avoid missed split in multi-arc ArcStrings

diff --git a/src/noding/NodableArcString.cpp b/src/noding/NodableArcString.cpp
index d05865e79..810258922 100644
--- a/src/noding/NodableArcString.cpp
+++ b/src/noding/NodableArcString.cpp
@@ -94,14 +94,18 @@ prepareArcPoints(const CircularArc& arc, std::vector<CoordinateXYZM> splitPoints
     {
         CoordinateXYZM p2;
         arc.getCoordinateSequence()->getAt(arc.getCoordinatePosition() + (isCCW ? 2 : 0), p2);
+        if (!splitPoints.empty() && splitPoints.back().equals2D(p2)) {
+            splitEnd = true;
+        }
         splitPoints.push_back(p2);
     }
 
 #if DEBUG_NODABLE_ARC_STRING
     std::cout << std::setprecision(17);
     std::cout << std::endl;
-    std::cout << "Edge from " << arc.p0() << " to " << arc.p2() << " has " << splitPoints.size() << " potential split points:" << std::endl;
-    std::cout << "Edge is CIRCULARSTRING " << *arc.getCoordinateSequence() << std::endl;
+    std::cout << "Arc from " << arc.p0() << " to " << arc.p2() << " has " << splitPoints.size() << " potential split points:" << std::endl;
+    std::cout << "Arc is CIRCULARSTRING " << *arc.getCoordinateSequence() << std::endl;
+    std::cout << "Reversed? " << !isCCW << std::endl;
     std::cout << "Start point is " << retained.back() << " pa " << paStart << std::endl;
     std::cout << "Potential split points:" << std::endl;
     for (std::size_t i = 0; i < splitPoints.size(); i++) {
@@ -215,7 +219,7 @@ prepareArcPoints(const CircularArc& arc, std::vector<CoordinateXYZM> splitPoints
     }
 
 #if DEBUG_NODABLE_ARC_STRING
-    std::cout << "Retained split points:" << std::endl;
+    std::cout << "Retained split points: (splitStart " << splitStart << " " << " splitEnd " << splitEnd << ")" << std::endl;
     for (std::size_t i = 0; i < retained.size(); i++) {
         std::cout << "  " << retained[i] << " paDiff " << pseudoAngleDiffCCW(paStart, geom::Quadrant::pseudoAngle(center, retained[i]));
         if (i > 0) {
@@ -282,6 +286,9 @@ NodableArcString::getNoded(std::vector<std::unique_ptr<ArcString>>& splitArcs) {
     ArcBuilder builder(splitArcs, getData(), m_constructZ, m_constructM);
 
     for (size_t arcIndex = 0; arcIndex < m_arcs.size(); arcIndex++) {
+#if DEBUG_NODABLE_ARC_STRING
+        std::cout << "arc " << arcIndex + 1 << " / " << m_arcs.size();
+#endif
         const CircularArc& toSplit = m_arcs[arcIndex];
         const geom::CoordinateXY& center = toSplit.getCenter();
         const double radius = toSplit.getRadius();
@@ -332,7 +339,6 @@ NodableArcString::getNoded(std::vector<std::unique_ptr<ArcString>>& splitArcs) {
             const bool isSplitPoint = (i < split.points.size() - 1) || split.splitEnd;
             if (isSplitPoint) {
                 builder.finish();
-
             }
         }
     }
diff --git a/tests/xmltester/tests/general/TestOverlayCurvesAA.xml b/tests/xmltester/tests/general/TestOverlayCurvesAA.xml
index 0629b027f..d47e974cb 100644
--- a/tests/xmltester/tests/general/TestOverlayCurvesAA.xml
+++ b/tests/xmltester/tests/general/TestOverlayCurvesAA.xml
@@ -1,4 +1,34 @@
 <run>
+    <case>
+        <desc>AA - simple polygons</desc>
+        <a>
+            CURVEPOLYGON(COMPOUNDCURVE(CIRCULARSTRING (10 100, 100 10, 100 60), (100 60, 10 100)))
+        </a>
+        <b>
+            CURVEPOLYGON(COMPOUNDCURVE((50 50, 200 50, 200 200, 50 200), CIRCULARSTRING (50 200, -9 100, 50 50)))
+        </b>
+        <test>
+            <op name="intersection" arg1="A" arg2="B">
+                CURVEPOLYGON (COMPOUNDCURVE (CIRCULARSTRING (-5.521402634079415 91.63934964816265, 1.9736670312808187 96.31281538666524, 10 100), (10 100, 100 60), CIRCULARSTRING (100 60, 101.69137093859678 55.056446403350975, 103.00735254367723 50), (103.00735254367723 50, 50 50), CIRCULARSTRING (50 50, 17.21604286900091 64.12172658671918, -5.521402634079415 91.63934964816265)))
+            </op>
+        </test>
+        <test>
+            <op name="union" arg1="A" arg2="B">
+                CURVEPOLYGON (COMPOUNDCURVE (CIRCULARSTRING (-5.521402634079415 91.63934964816265, -4.851528401625146 159.70036595476157, 50 200), (50 200, 200 200, 200 50, 103.00735254367723 50), CIRCULARSTRING (103.00735254367723 50, 10.05349282186549 -30.02054890272217, -5.521402634079415 91.63934964816265)))
+            </op>
+        </test>
+        <test>
+            <op name="difference" arg1="A" arg2="B">
+                CURVEPOLYGON (COMPOUNDCURVE (CIRCULARSTRING (-5.521402634079415 91.63934964816265, 17.21604286900091 64.12172658671918, 50 50), (50 50, 103.00735254367723 50), CIRCULARSTRING (103.00735254367723 50, 10.05349282186549 -30.02054890272217, -5.521402634079415 91.63934964816265)))
+            </op>
+        </test>
+        <test>
+            <op name="symdifference" arg1="A" arg2="B">
+                MULTISURFACE (CURVEPOLYGON (COMPOUNDCURVE (CIRCULARSTRING (-5.521402634079415 91.63934964816265, 17.21604286900091 64.12172658671918, 50 50), (50 50, 103.00735254367723 50), CIRCULARSTRING (103.00735254367723 50, 10.05349282186549 -30.02054890272217, -5.521402634079415 91.63934964816265))), CURVEPOLYGON (COMPOUNDCURVE (CIRCULARSTRING (-5.521402634079415 91.63934964816265, -4.851528401625146 159.70036595476157, 50 200), (50 200, 200 200, 200 50, 103.00735254367723 50), CIRCULARSTRING (103.00735254367723 50, 101.69137093859678 55.056446403350975, 100 60), (100 60, 10 100), CIRCULARSTRING (10 100, 1.9736670312808187 96.31281538666524, -5.521402634079415 91.63934964816265))))
+            </op>
+        </test>
+    </case>
+
     <case>
         <desc>AA - A with hole intersecting B</desc>
         <a>
@@ -12,5 +42,82 @@
                 CURVEPOLYGON (COMPOUNDCURVE ((80 136.50148808205722, 80 160), (80 160, 160 160, 160 100, 127.04025757937788 100), CIRCULARSTRING (127.04025757937788 100, 106.68619012043186 122.3309157911624, 80 136.50148808205722)))
             </op>
         </test>
+        <test>
+            <op name="union" arg1="A" arg2="B">
+                CURVEPOLYGON ((20 20, 20 160, 80 160, 80 240, 220 240, 220 100, 160 100, 160 20, 20 20), COMPOUNDCURVE ((40 40, 140 40), CIRCULARSTRING (140 40, 138.89595632376427 71.16115566898841, 127.04025757937788 100), (127.04025757937788 100, 80 100, 80 136.50148808205722), CIRCULARSTRING (80 136.50148808205722, 60.20129186630378 140.55220101502292, 40 140), (40 140, 40 40)))
+            </op>
+        </test>
+        <test>
+            <op name="difference" arg1="A" arg2="B">
+                CURVEPOLYGON (COMPOUNDCURVE ((20 20, 20 160, 80 160, 80 136.50148808205722), CIRCULARSTRING (80 136.50148808205722, 60.20129186630378 140.55220101502292, 40 140), (40 140, 40 40, 140 40), CIRCULARSTRING (140 40, 138.89595632376427 71.16115566898841, 127.04025757937788 100), (127.04025757937788 100, 160 100, 160 20, 20 20)))
+            </op>
+        </test>
+        <test>
+            <op name="symdifference" arg1="A" arg2="B">
+                MULTISURFACE (CURVEPOLYGON (COMPOUNDCURVE ((20 20, 20 160, 80 160, 80 136.50148808205722), CIRCULARSTRING (80 136.50148808205722, 60.20129186630378 140.55220101502292, 40 140), (40 140, 40 40, 140 40), CIRCULARSTRING (140 40, 138.89595632376427 71.16115566898841, 127.04025757937788 100), (127.04025757937788 100, 160 100, 160 20, 20 20))), CURVEPOLYGON (COMPOUNDCURVE ((80 100, 80 136.50148808205722), CIRCULARSTRING (80 136.50148808205722, 106.68619012043186 122.3309157911624, 127.04025757937788 100), (127.04025757937788 100, 80 100))), ((80 160, 80 240, 220 240, 220 100, 160 100, 160 160, 80 160)))
+            </op>
+        </test>
+    </case>
+    <case>
+        <desc>AA - simple polygons #2</desc>
+        <a>
+            CURVEPOLYGON (COMPOUNDCURVE((20 340, 330 380, 50 40), CIRCULARSTRING (50 40, 70 220, 20 340)))
+
+        </a>
+        <b>
+            POLYGON(
+            (210 320, 140 270, 0 270, 140 220, 210 320))
+        </b>
+        <test>
+            <op name="intersection" arg1="A" arg2="B">
+                CURVEPOLYGON (COMPOUNDCURVE ((56.278836074826415 270, 140 270, 210 320, 140 220, 63.6291020022965 247.27532071346553), CIRCULARSTRING (63.6291020022965 247.27532071346553, 60.17196289508064 258.70817016660806, 56.278836074826415 270)))
+            </op>
+        </test>
+        <test>
+            <op name="union" arg1="A" arg2="B">
+                CURVEPOLYGON (COMPOUNDCURVE ((0 270, 56.278836074826415 270), CIRCULARSTRING (56.278836074826415 270, 40.36422766234557 306.1530500525802, 20 340), (20 340, 330 380, 50 40), CIRCULARSTRING (50 40, 74.61109542602588 142.46747319494153, 63.6291020022965 247.27532071346553), (63.6291020022965 247.27532071346553, 0 270)))
+            </op>
+        </test>
+        <test>
+            <op name="difference" arg1="A" arg2="B">
+                CURVEPOLYGON (COMPOUNDCURVE ((20 340, 330 380, 50 40), CIRCULARSTRING (50 40, 74.61109542602588 142.46747319494153, 63.6291020022965 247.27532071346553), (63.6291020022965 247.27532071346553, 140 220, 210 320, 140 270, 56.278836074826415 270), CIRCULARSTRING (56.278836074826415 270, 40.36422766234557 306.1530500525802, 20 340)))
+            </op>
+        </test>
+        <test>
+            <op name="symdifference" arg1="A" arg2="B">
+                MULTISURFACE (CURVEPOLYGON (COMPOUNDCURVE ((20 340, 330 380, 50 40), CIRCULARSTRING (50 40, 74.61109542602588 142.46747319494153, 63.6291020022965 247.27532071346553), (63.6291020022965 247.27532071346553, 140 220, 210 320, 140 270, 56.278836074826415 270), CIRCULARSTRING (56.278836074826415 270, 40.36422766234557 306.1530500525802, 20 340))), CURVEPOLYGON (COMPOUNDCURVE ((0 270, 56.278836074826415 270), CIRCULARSTRING (56.278836074826415 270, 60.17196289508064 258.70817016660806, 63.6291020022965 247.27532071346553), (63.6291020022965 247.27532071346553, 0 270))))
+            </op>
+        </test>
+
+    </case>
+    <case>
+        <desc>AA - simple polygons intersecting in P, L and A</desc>
+        <a>
+            CURVEPOLYGON(COMPOUNDCURVE((0 0, 110 0), CIRCULARSTRING (110 0, 90 20, 110 60), (110 60, 40 60, 100 100), CIRCULARSTRING (100 100, 150 150, 100 200), (100 200, 40 220, 110 260), CIRCULARSTRING (110 260, 50 280, 0 260, -50 130, 0 0)))
+        </a>
+        <b>
+            CURVEPOLYGON(COMPOUNDCURVE(CIRCULARSTRING(220 0, 120 20, 110 0, 90 20, 110 60), (110 60, 180 60, 100 150, 180 220, 110 260, 220 260, 220 0)))
+        </b>
+        <test>
+            <op name="intersection" arg1="A" arg2="B">
+                GEOMETRYCOLLECTION (CURVEPOLYGON (COMPOUNDCURVE ((100 150, 137.6288347353439 182.92523039342592), CIRCULARSTRING (137.6288347353439 182.92523039342592, 149.90186898086148 146.8689503011078, 133.218191941496 112.62953406581698), (133.218191941496 112.62953406581698, 100 150))), CIRCULARSTRING (110 0, 90 20, 110 60), POINT (110 260))
+            </op>
+        </test>
+        <test>
+            <op name="union" arg1="A" arg2="B">
+                CURVEPOLYGON (COMPOUNDCURVE (CIRCULARSTRING (0 0, -50 130, 0 260, 50 280, 110 260), (110 260, 220 260, 220 0), CIRCULARSTRING (220 0, 120 20, 110 0), (110 0, 0 0)), COMPOUNDCURVE ((40 60, 110 60, 180 60, 133.218191941496 112.62953406581698), CIRCULARSTRING (133.218191941496 112.62953406581698, 117.76902787564433 103.26391492267913, 100 100), (100 100, 40 60)), COMPOUNDCURVE ((40 220, 100 200), CIRCULARSTRING (100 200, 120.66081412152852 195.5316456965444, 137.6288347353439 182.92523039342592), (137.6288347353439 182.92523039342592, 180 220, 110 260), (110 260, 40 220)))
+            </op>
+        </test>
+        <test>
+            <op name="difference" arg1="A" arg2="B">
+                CURVEPOLYGON (COMPOUNDCURVE (CIRCULARSTRING (0 0, -50 130, 0 260, 50 280, 110 260), (110 260, 40 220, 100 200), CIRCULARSTRING (100 200, 120.66081412152852 195.5316456965444, 137.6288347353439 182.92523039342592), (137.6288347353439 182.92523039342592, 100 150, 133.218191941496 112.62953406581698), CIRCULARSTRING (133.218191941496 112.62953406581698, 117.76902787564433 103.26391492267913, 100 100), (100 100, 40 60, 110 60), CIRCULARSTRING (110 60, 90 20, 110 0), (110 0, 0 0)))
+            </op>
+        </test>
+        <test>
+            <op name="symdifference" arg1="A" arg2="B">
+                CURVEPOLYGON (COMPOUNDCURVE (CIRCULARSTRING (0 0, -50 130, 0 260, 50 280, 110 260), (110 260, 220 260, 220 0), CIRCULARSTRING (220 0, 120 20, 110 0), (110 0, 0 0)), COMPOUNDCURVE ((40 60, 110 60, 180 60, 133.218191941496 112.62953406581698), CIRCULARSTRING (133.218191941496 112.62953406581698, 117.76902787564433 103.26391492267913, 100 100), (100 100, 40 60)), COMPOUNDCURVE ((100 150, 133.218191941496 112.62953406581698), CIRCULARSTRING (133.218191941496 112.62953406581698, 149.90186898086148 146.8689503011078, 137.6288347353439 182.92523039342592), (137.6288347353439 182.92523039342592, 100 150)), COMPOUNDCURVE ((40 220, 100 200), CIRCULARSTRING (100 200, 120.66081412152852 195.5316456965444, 137.6288347353439 182.92523039342592), (137.6288347353439 182.92523039342592, 180 220, 110 260), (110 260, 40 220)))
+            </op>
+        </test>
+
     </case>
 </run>

commit 92b27f72feeda5a27e3747abfda79c071a1fb4d4
Author: Daniel Baston <dbaston at gmail.com>
Date:   Fri Jul 10 13:15:37 2026 -0400

    XMLTester: skip validity testing for curved results

diff --git a/tests/xmltester/XMLTester.cpp b/tests/xmltester/XMLTester.cpp
index 0ead98773..e285ec4d9 100644
--- a/tests/xmltester/XMLTester.cpp
+++ b/tests/xmltester/XMLTester.cpp
@@ -479,16 +479,29 @@ bool
 XMLTester::testValid(const geom::Geometry* g, const std::string& label)
 {
     operation::valid::IsValidOp ivo(g);
-    bool valid = ivo.isValid();
-    if(! valid) {
-        const TopologyValidationError* err = ivo.getValidationError();
-        std::cerr << *curr_file << ":"
-                  << " case" << caseCount << ":"
-                  << " test" << testCount << ": "
-                  << " invalid geometry (" << label
-                  << "): " << err->toString() << std::endl;
+    try {
+        bool valid = ivo.isValid();
+
+        if(! valid) {
+            const TopologyValidationError* err = ivo.getValidationError();
+            std::cerr << *curr_file << ":"
+                      << " case" << caseCount << ":"
+                      << " test" << testCount << ": "
+                      << " invalid geometry (" << label
+                      << "): " << err->toString() << std::endl;
+        }
+
+        return valid;
+    } catch (const geos::util::UnsupportedOperationException& ex) {
+        if (g->hasCurvedComponents()) {
+            const std::string message(ex.what());
+            if (message.find("Curved types not supported") != std::string::npos) {
+                return true;
+            }
+        }
+
+        throw;
     }
-    return valid;
 }
 
 /**

commit 7f1c5dca809b3dc4b6336ab3474011a1a57dd2ba
Author: Daniel Baston <dbaston at gmail.com>
Date:   Fri Jul 10 13:04:36 2026 -0400

    XMLTester: treat unexpected exceptions as test failures

diff --git a/tests/xmltester/XMLTester.cpp b/tests/xmltester/XMLTester.cpp
index 16b1690aa..0ead98773 100644
--- a/tests/xmltester/XMLTester.cpp
+++ b/tests/xmltester/XMLTester.cpp
@@ -1015,6 +1015,7 @@ void Test::execute(Geometry* geomA, Geometry* geomB)
         else {
             std::cerr << "EXCEPTION in " << tester.testcaseRef() << ": " << e.what()
                       << std::endl;
+            isSuccess = false;
             actualResultStr = e.what();
         }
     }
@@ -1022,6 +1023,7 @@ void Test::execute(Geometry* geomA, Geometry* geomB)
         std::cerr << "Unknown EXCEPTION in "
                   << tester.testcaseRef()
                   << std::endl;
+        isSuccess = false;
         actualResultStr = "Unknown exception thrown";
     }
 }

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

Summary of changes:
 src/noding/NodableArcString.cpp                    |  14 ++-
 tests/unit/noding/NodableArcStringTest.cpp         |  53 ++++++++++
 tests/xmltester/XMLTester.cpp                      |  51 +++++++---
 .../tests/general/TestOverlayCurvesAA.xml          | 107 +++++++++++++++++++++
 4 files changed, 206 insertions(+), 19 deletions(-)


hooks/post-receive
-- 
GEOS


More information about the geos-commits mailing list