[geos-commits] [SCM] GEOS branch 3.13 updated. a04be684e14de98896b8047d7076ab2ab7030785
git at osgeo.org
git at osgeo.org
Mon May 26 13:41:48 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.13 has been updated
via a04be684e14de98896b8047d7076ab2ab7030785 (commit)
via 4cdfb40459447f0b44e0db7d3dbd0d7bfff029c3 (commit)
from a6279fc3eeaf57d5cfd543c621ec15c59474f273 (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 a04be684e14de98896b8047d7076ab2ab7030785
Author: Martin Davis <mtnclimb at gmail.com>
Date: Mon May 26 13:41:26 2025 -0700
Update NEWS
diff --git a/NEWS.md b/NEWS.md
index 84a803e73..b08d0494a 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -5,6 +5,7 @@
- Fixes/Improvements:
- Fix GeometryCollections in coverageSimplify cause segfault (GH-1250, Paul Ramsey)
- 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.13.1
2025-03-03
commit 4cdfb40459447f0b44e0db7d3dbd0d7bfff029c3
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 4fc9d578a..2941c020a 100644
--- a/src/operation/buffer/SubgraphDepthLocater.cpp
+++ b/src/operation/buffer/SubgraphDepthLocater.cpp
@@ -70,8 +70,35 @@ public:
}
/**
- * Defines a comparison 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 | 1 +
src/operation/buffer/SubgraphDepthLocater.cpp | 112 ++++++++++++++++++--------
tests/unit/operation/buffer/BufferOpTest.cpp | 13 +++
3 files changed, 91 insertions(+), 35 deletions(-)
hooks/post-receive
--
GEOS
More information about the geos-commits
mailing list