[geos-commits] [SCM] GEOS branch 3.11 updated. 3eb40b554c9f9fa8f86c11064d10eb6deba4c463
git at osgeo.org
git at osgeo.org
Mon May 26 14:10:08 PDT 2025
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, 3.11 has been updated
via 3eb40b554c9f9fa8f86c11064d10eb6deba4c463 (commit)
via 8a03ecc783cf79c0a4dea3bba883b49b4dd4579a (commit)
from 1a93fbe4f262fd196cdb153782366e8436fb630a (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 3eb40b554c9f9fa8f86c11064d10eb6deba4c463
Author: Martin Davis <mtnclimb at gmail.com>
Date: Mon May 26 14:09:46 2025 -0700
Update NEWS
diff --git a/NEWS.md b/NEWS.md
index 1505d33d0..e545f4296 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -2,7 +2,7 @@
2025-xx-xx
- Fixes/Improvements:
- -
+ - Fix DepthSegment comparison logic (really this time) (GH-1266, Martin Davis)
## Changes in 3.11.5
2025-03-03
commit 8a03ecc783cf79c0a4dea3bba883b49b4dd4579a
Author: Martin Davis <mtnclimb at gmail.com>
Date: Mon May 26 14:09:17 2025 -0700
Fix DepthSegment comparison logic
diff --git a/src/operation/buffer/SubgraphDepthLocater.cpp b/src/operation/buffer/SubgraphDepthLocater.cpp
index 44d06c5ec..2ce65d368 100644
--- a/src/operation/buffer/SubgraphDepthLocater.cpp
+++ b/src/operation/buffer/SubgraphDepthLocater.cpp
@@ -70,8 +70,35 @@ public:
}
/**
- * Defines a comparision operation on DepthSegments
- * which orders them left to right
+ * Compares a point to a segment for left/right position,
+ * as long as the point lies within the segment Y extent.
+ * Otherwise the point is not comparable.
+ * If the point is not comparable or it lies on the segment
+ * returns 0.
+ */
+ int
+ comparePointInYExtent(const Coordinate& p, const LineSegment& seg) const
+ {
+ //-- if point is comparable to segment
+ if (p.y >= seg.minY() && p.y <= seg.maxY()) {
+ //-- flip sign, since orientation and order relation are opposite
+ int orient = seg.orientationIndex(p);
+ switch (orient) {
+ case Orientation::LEFT: return -1;
+ case Orientation::RIGHT: return 1;
+ }
+ //-- collinear, so indeterminate
+ }
+ //-- not computable
+ return 0;
+ }
+
+ /**
+ * A comparison operation which orders segments left to right
+ * along some horizontal line.
+ * If segments don't touch the same line,
+ * or touch at the same point,
+ * they are compared in their Y extent.
*
* <pre>
* DS1 < DS2 if DS1.seg is left of DS2.seg
@@ -85,45 +112,60 @@ public:
compareTo(const DepthSegment& other) const
{
/**
- * If segment envelopes do not overlap, then
- * can use standard segment lexicographic ordering.
+ * If segments are disjoint in X, X values provides ordering.
+ * This is the most common case.
*/
- if (upwardSeg.minX() >= other.upwardSeg.maxX()
- || upwardSeg.maxX() <= other.upwardSeg.minX()
- || upwardSeg.minY() >= other.upwardSeg.maxY()
- || upwardSeg.maxY() <= other.upwardSeg.minY()) {
- return upwardSeg.compareTo(other.upwardSeg);
- };
-
+ if (upwardSeg.minX() > other.upwardSeg.maxX())
+ return 1;
+ if (upwardSeg.maxX() < other.upwardSeg.minX())
+ return -1;
/**
- * Otherwise if envelopes overlap, use relative segment orientation.
- *
- * Collinear segments should be evaluated by previous logic
+ * The segments Y ranges should intersect since they lie on same stabbing line.
+ * But check for this and provide a result based on Y ordering
*/
- int orientIndex = upwardSeg.orientationIndex(&(other.upwardSeg));
-
- /*
- * If comparison between this and other is indeterminate,
- * try the opposite call order.
- * orientationIndex value is 1 if this is left of other,
- * so have to flip sign to get proper comparison value of
- * -1 if this is leftmost
- */
- if(orientIndex == 0) {
- orientIndex = -1 * other.upwardSeg.orientationIndex(&upwardSeg);
- }
-
- // if orientation is determinate, return it
- if(orientIndex != 0) {
- return orientIndex;
- }
-
+ if (upwardSeg.minY() > other.upwardSeg.maxY())
+ return 1;
+ if (upwardSeg.maxY() < other.upwardSeg.minY())
+ return -1;
+
/**
- * If segment envelopes overlap and they are collinear,
- * since segments do not cross they must be equal.
+ * Check if some segment point is left or right
+ * of the other segment in its Y extent.
*/
+ int comp00 = comparePointInYExtent(upwardSeg.p0, other.upwardSeg);
+ if (comp00 != 0) return comp00;
+ int comp01 = comparePointInYExtent(upwardSeg.p1, other.upwardSeg);
+ if (comp01 != 0) return comp01;
+ //-- negate orientation for other/this checks
+ int comp10 = -comparePointInYExtent(other.upwardSeg.p0, upwardSeg);
+ if (comp10 != 0) return comp10;
+ int comp11 = -comparePointInYExtent(other.upwardSeg.p1, upwardSeg);
+ if (comp11 != 0) return comp11;
+
+ /**
+ * If point checks in Y range are indeterminate,
+ * segments touch at a point
+ * and lie above and below that point, or are horizontal.
+ * Order according to their Y values.
+ * (The ordering in this case doesn't matter, it just has to be consistent)
+ */
+ if (upwardSeg.maxY() > other.upwardSeg.maxY())
+ return 1;
+ if (upwardSeg.maxY() < other.upwardSeg.maxY())
+ return -1;
+
+ /**
+ * If both are horizontal order by X
+ */
+ if (upwardSeg.isHorizontal() && other.upwardSeg.isHorizontal()) {
+ if (upwardSeg.minX() < other.upwardSeg.minX())
+ return -1;
+ if (upwardSeg.minX() > other.upwardSeg.minX())
+ return 1;
+ }
+
// assert: segments are equal
- return 0;
+ return 0;
}
};
diff --git a/tests/unit/operation/buffer/BufferOpTest.cpp b/tests/unit/operation/buffer/BufferOpTest.cpp
index dff461b16..1103a0b46 100644
--- a/tests/unit/operation/buffer/BufferOpTest.cpp
+++ b/tests/unit/operation/buffer/BufferOpTest.cpp
@@ -660,4 +660,17 @@ void object::test<26>
"POLYGON ((0.73 0.05, 0.67 -0.13, 0.58 -0.31, 0.46 -0.46, 0.31 -0.58, 0.13 -0.67, -0.05 -0.73, -0.25 -0.75, -0.75 -0.75, -0.95 -0.73, -1.13 -0.67, -1.31 -0.58, -1.46 -0.46, -1.58 -0.31, -1.67 -0.13, -1.73 0.05, -1.75 0.25, -1.75 0.75, -1.73 0.95, -1.67 1.13, -1.58 1.31, -1.46 1.46, -1.31 1.58, -1.13 1.67, -0.95 1.73, -0.75 1.75, -0.25 1.75, -0.05 1.73, 0.13 1.67, 0.31 1.58, 0.46 1.46, 0.58 1.31, 0.67 1.13, 0.73 0.95, 0.75 0.75, 0.75 0.25, 0.73 0.05))");
}
+// testBufferByZeroKeepsAllElements
+// Test a buffer-by-zero case which revealed a bug in the DeptSegment comparator.
+// See https://github.com/locationtech/jts/issues/1131
+template<>
+template<>
+void object::test<28>
+()
+{
+ std::string wkt = "MULTIPOLYGON (((24 95.239, 24 96, 24 99, 24.816 99, 24 95.239)), ((3 90, 3 93, 3 96, 3 99, 21 99, 21 96, 21 93, 21 90, 3 90)))";
+ checkBuffer(wkt, 0, 0.01,
+"MULTIPOLYGON (((24 95.239, 24 96, 24 99, 24.816 99, 24 95.239)), ((3 90, 3 93, 3 96, 3 99, 21 99, 21 96, 21 93, 21 90, 3 90)))");
+}
+
} // namespace tut
-----------------------------------------------------------------------
Summary of changes:
NEWS.md | 2 +-
src/operation/buffer/SubgraphDepthLocater.cpp | 110 ++++++++++++++++++--------
tests/unit/operation/buffer/BufferOpTest.cpp | 13 +++
3 files changed, 90 insertions(+), 35 deletions(-)
hooks/post-receive
--
GEOS
More information about the geos-commits
mailing list