[geos-commits] [SCM] GEOS branch 3.12 updated. 0aef237c159ad9c92857134af0831e7f03a3b276
git at osgeo.org
git at osgeo.org
Mon May 26 13:50:25 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.12 has been updated
via 0aef237c159ad9c92857134af0831e7f03a3b276 (commit)
via d4882702d6c676a59130b31960bc245074e6f91c (commit)
from 86039e06d249dbae6b53a9ff6480b7a36d24cc06 (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 0aef237c159ad9c92857134af0831e7f03a3b276
Author: Martin Davis <mtnclimb at gmail.com>
Date: Mon May 26 13:50:01 2025 -0700
Update NEWS
diff --git a/NEWS.md b/NEWS.md
index 17e9c0760..d3e916e2f 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -3,7 +3,7 @@
- Fixes:
- Fix OverlayNG coordinate dimemsion handling for EMPTY geometries (GH-1258, Martin Davis)
-
+ - Fix DepthSegment comparison logic (really this time) (GH-1266, Martin Davis)
## Changes in 3.12.3
2025-03-03
commit d4882702d6c676a59130b31960bc245074e6f91c
Author: Martin Davis <mtnclimb at gmail.com>
Date: Mon May 26 13:36:05 2025 -0700
Fix DepthSegment comparison logic (#1266)
diff --git a/src/operation/buffer/SubgraphDepthLocater.cpp b/src/operation/buffer/SubgraphDepthLocater.cpp
index 7fa3c90eb..2941c020a 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
@@ -84,47 +111,62 @@ public:
int
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 (upwardSeg.minY() > other.upwardSeg.maxY())
+ return 1;
+ if (upwardSeg.maxY() < other.upwardSeg.minY())
+ return -1;
+
+ /**
+ * Check if some segment point is left or right
+ * of the other segment in its Y extent.
*/
- if(orientIndex == 0) {
- orientIndex = -1 * other.upwardSeg.orientationIndex(&upwardSeg);
+ 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;
}
-
- // if orientation is determinate, return it
- if(orientIndex != 0) {
- return orientIndex;
- }
-
- /**
- * If segment envelopes overlap and they are collinear,
- * since segments do not cross they must be equal.
- */
+
// assert: segments are equal
- return 0;
- }
+ return 0; }
};
struct DepthSegmentLessThan {
diff --git a/tests/unit/operation/buffer/BufferOpTest.cpp b/tests/unit/operation/buffer/BufferOpTest.cpp
index 342f95db2..39f8592bb 100644
--- a/tests/unit/operation/buffer/BufferOpTest.cpp
+++ b/tests/unit/operation/buffer/BufferOpTest.cpp
@@ -611,4 +611,17 @@ void object::test<27>
"POLYGON ((48267.2218198241 -49049.37231112561, 44430.1 -55696.500291383236, 44430.1 -55107.58561879013, 44506.96594366424 -54974.50014155032, 44507.05088958367 -54974.309530288774, 44507.09442572395 -54974.10543945913, 44507.09465615313 -54973.896756903174, 44507.05157083636 -54973.69257042533, 44506.96704607295 -54973.50177203271, 44430.1 -54839.73314639927, 44430.1 -51569.2, 44430.08071956347 -51569.00457958696, 44430.02362172434 -51568.81669475566, 44429.93090822513 -51568.64359050924, 44429.80615417933 -51568.49194189856, 42172.42282165639 -49317.178566110095, 48267.2218198241 -49049.37231112561))");
}
+// 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 | 112 ++++++++++++++++++--------
tests/unit/operation/buffer/BufferOpTest.cpp | 13 +++
3 files changed, 91 insertions(+), 36 deletions(-)
hooks/post-receive
--
GEOS
More information about the geos-commits
mailing list