Open grimsa opened 2 years ago
Thanks for the detailed issue! I don't see anything wrong with the way you are using JTS (and it's interesting seeing JTS being used with modern functional Java code).
This does look like some sort of bug. I can run your test code and get the failure. The odd thing is that if I load the input GeometryCollection into the TestBuilder and run it it works correctly!
GEOMETRYCOLLECTION (POLYGON ((-16.15907384118054 1.0157206673651495, -16.28767148661218 7.6835050482212575, -13.719459554848422 5.212481574525698, -13.639456293556348 1.0643148816523527, -16.15907384118054 1.0157206673651495)), POLYGON ((-12.725226307666448 1.0819470369308437, -13.639456293556348 1.0643148816523527, -13.719459768757051 5.212481780339414, -12.78759751645274 4.315883851167196, -12.725226307666448 1.0819470369308437)), POLYGON ((-13.621824029083443 0.15008489786842, -16.14144162383529 0.1014906826722966, -16.15907384118054 1.0157206673651493, -13.639456293556348 1.0643148816523527, -13.621824029083443 0.15008489786842)), POLYGON ((-17.219533690879903 8.580102931174729, -16.28767148661218 7.683505048221257, -16.15907384118054 1.0157206673651495, -17.073303827070436 0.9980885120866584, -17.219533690879903 8.580102931174729)), POLYGON ((-12.707594043193543 0.1677170531469111, -13.621824029083443 0.1500848978684201, -13.639456293556348 1.0643148816523527, -12.725226307666448 1.0819470369308437, -12.707594043193543 0.1677170531469111)), POLYGON ((-17.055671609725188 0.0838585273938056, -17.073303827070436 0.9980885120866584, -16.15907384118054 1.0157206673651493, -16.14144162383529 0.1014906826722966, -17.055671609725188 0.0838585273938056)))
I'll keep digging and try and find out what's going on. It's possible it's something to do with numeric precision that only shows up when the data is loaded as Java double-precision literals - although would be surprising, given the extensive robustness heuristics in OverlayNG.
I think the problem is related to the fact that you are specifying 17 digits of precision in the input ordinates. For instance, this one. 0.15008489786842003
. If I truncate this to 16 digits of precision (0.15008489786842
) then the test case works.
I still think the various levels of robust geometric code in OverlayNG should handle this - but obviously it doesn't! Perhaps it's not surprising - 17 digits is right at the limit of double-precision floating-point representation.
I'll keep digging, but in the meantime you can round off your input numbers a bit.
The same problem occurs when computing the union of p3
and p5
, so that simplifies testing.
A test case is here: https://github.com/dr-jts/jts/tree/fix-union-highprec
Ran into a similar issue of union of polygons with very high precision coordinates producing an empty result. Works fine when serialized to WKT and loaded into test builder. Did not check against latest JTS snapshot.
Test Case:
@Test
void geometryCollectionUnion() {
var gf = new GeometryFactory();
var p1 = gf.createPolygon(new Coordinate[]{
new Coordinate(-0.49524584515584785, 2.254321259525603),
new Coordinate(-0.4518674095819571, 1.6850769474821623),
new Coordinate(0.11737696012368323, 1.7284553797131785),
new Coordinate(-3.208506829071115, -2.146129227235706),
new Coordinate(-3.821129633016156, -1.6202633492159437),
new Coordinate(-0.49524584515584785, 2.254321259525603)
});
var p2 = gf.createPolygon(new Coordinate[]{
new Coordinate(-0.49524584515584785, 2.254321259525603, 6.986031855278883),
new Coordinate(-0.4518674095819571, 1.6850769474821623, 6.986031855334046),
new Coordinate(0.11737696012368318, 1.7284553797131785, 6.986031855278883),
new Coordinate(-0.49524584515584785, 2.254321259525603, 6.986031855278883)
});
// Passes
assertFalse(p2.union(p1).isEmpty(), "p2 union p1");
// Passes
assertFalse(p1.union(p2).isEmpty(), "p1 union p2");
// Fails in JTS 1.18.2 with OverlayNG
assertFalse(gf.createGeometryCollection(new Polygon[]{p1, p2}).union().isEmpty(), "geometry collection union");
}
(Not sure if this is a bug or just me using JTS in an unsupported way)
The need: union ~5-20 polygons that may be (slightly) overlapping
My current implementation uses
new GeometryCollection(polygons).union()
and it has worked reliably so far.However, I found one case where the union does not fail, yet the produced polygon is missing large areas.
Input:
Union result (red) over input (blue):
Versions used:
Test case:
Some notes:
GeometryCollection#union
andMultiPolygon#union
produce the same incorrect result (displayed above)jts.overlay=ng
flag makes the test pass - all 3 ways produce the same correct resultSo I guess my questions are:
GeometryCollection
/MultiPolygon
produce a correct union for this slightly overlapping set of polygons? (i.e. is it supported)