[geos-commits] [SCM] GEOS branch main updated. 00648624efd1b4a3650b6c7a473fcd3647957406
git at osgeo.org
git at osgeo.org
Tue Oct 20 07:31:49 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 00648624efd1b4a3650b6c7a473fcd3647957406 (commit)
from 9f80ea6d9293db0090469070caf58ab6f34e936d (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 00648624efd1b4a3650b6c7a473fcd3647957406
Author: Daniel Baston <dbaston at gmail.com>
Date: Tue Oct 20 10:31:30 2026 -0400
CircularArcIntesector: check for common points before excluding based on distance (#1559)
diff --git a/src/algorithm/CircularArcIntersector.cpp b/src/algorithm/CircularArcIntersector.cpp
index d503fb384..a41265367 100644
--- a/src/algorithm/CircularArcIntersector.cpp
+++ b/src/algorithm/CircularArcIntersector.cpp
@@ -182,6 +182,30 @@ CircularArcIntersector::intersects(const CircularArc& arc, const CoordinateSeque
}
}
+static std::vector<CoordinateXY>
+getCommonPoints(const CircularArc& arc1, const CircularArc& arc2)
+{
+ std::vector<CoordinateXY> ret;
+ const CoordinateXY& ap0 = arc1.p0();
+ const CoordinateXY& ap1 = arc1.p1();
+ const CoordinateXY& ap2 = arc1.p2();
+ const CoordinateXY& bp0 = arc2.p0();
+ const CoordinateXY& bp1 = arc2.p1();
+ const CoordinateXY& bp2 = arc2.p2();
+
+ if (ap0 == bp0 || ap0 == bp1 || ap0 == bp2) {
+ ret.push_back(ap0);
+ }
+ if (ap1 == bp0 || ap1 == bp1 || ap1 == bp2) {
+ ret.push_back(ap1);
+ }
+ if (ap2 == bp0 || ap2 == bp1 || ap2 == bp2) {
+ ret.push_back(ap2);
+ }
+
+ return ret;
+}
+
void
CircularArcIntersector::intersects(const CircularArc& arc1, const CircularArc& arc2)
{
@@ -217,16 +241,20 @@ CircularArcIntersector::intersects(const CircularArc& arc1, const CircularArc& a
const auto d = c1.distance(c2);
- if (d > r1 + r2) {
- // Circles are disjoint
- result = NO_INTERSECTION;
- return;
- }
+ auto commonPoints = getCommonPoints(arc1, arc2);
- if (d < std::abs(r1-r2)) {
- // One circle contained within the other; arcs cannot intersect
- result = NO_INTERSECTION;
- return;
+ if (commonPoints.empty()) {
+ if (d > r1 + r2) {
+ // Circles are disjoint
+ result = NO_INTERSECTION;
+ return;
+ }
+
+ if (d < std::abs(r1-r2)) {
+ // One circle contained within the other; arcs cannot intersect
+ result = NO_INTERSECTION;
+ return;
+ }
}
// TODO because the circle center calculation is inexact we need some kind of tolerance here.
@@ -253,22 +281,8 @@ CircularArcIntersector::intersects(const CircularArc& arc1, const CircularArc& a
CoordinateXY isect0{p.x + h* dy/d, p.y - h* dx/d };
CoordinateXY isect1{p.x - h* dy/d, p.y + h* dx/d };
- // Check to see if computed intersection points are inexact versions of an endpoint intersection
- const CoordinateXY& ap0 = arc1.p0();
- const CoordinateXY& ap1 = arc1.p1();
- const CoordinateXY& ap2 = arc1.p2();
- const CoordinateXY& bp0 = arc2.p0();
- const CoordinateXY& bp1 = arc2.p1();
- const CoordinateXY& bp2 = arc2.p2();
-
- if (ap0 == bp0 || ap0 == bp1 || ap0 == bp2) {
- closestPoint(isect0, isect1, 2, ap0) = ap0;
- }
- if (ap1 == bp0 || ap1 == bp1 || ap1 == bp2) {
- closestPoint(isect0, isect1, 2, ap1) = ap1;
- }
- if (ap2 == bp0 || ap2 == bp1 || ap2 == bp2) {
- closestPoint(isect0, isect1, 2, ap2) = ap2;
+ for (const auto& pt : commonPoints) {
+ closestPoint(isect0, isect1, 2 , pt) = pt;
}
if (arc1.containsPointOnCircle(isect0) && arc2.containsPointOnCircle(isect0)) {
diff --git a/tests/unit/algorithm/CircularArcIntersectorTest.cpp b/tests/unit/algorithm/CircularArcIntersectorTest.cpp
index 63695fb9b..518de55e2 100644
--- a/tests/unit/algorithm/CircularArcIntersectorTest.cpp
+++ b/tests/unit/algorithm/CircularArcIntersectorTest.cpp
@@ -1823,6 +1823,18 @@ void object::test<91>()
XY{-3, 4});
}
+template<>
+template<>
+void object::test<92>()
+{
+ set_test_name("arcs intersect at shared vertex when inexact distance calculation says they cannot");
+
+ checkIntersection(XY{5, 0}, XY{6.530331962423936, 32.9099081287533}, XY{39.1383458646334, 37.61324718856101},
+ XY{5, 0}, XY{-13.013189892510923, 476.4218618845866}, XY{426.8482396243887, 660.3353967726679},
+ CircularArcIntersector::ONE_POINT_INTERSECTION,
+ XY{5, 0});
+}
+
// TODO: check Z values of arc result centerpoints
// TODO: add tests for seg/seg
-----------------------------------------------------------------------
Summary of changes:
src/algorithm/CircularArcIntersector.cpp | 64 +++++++++++++---------
.../unit/algorithm/CircularArcIntersectorTest.cpp | 12 ++++
2 files changed, 51 insertions(+), 25 deletions(-)
hooks/post-receive
--
GEOS
More information about the geos-commits
mailing list