Closed i23098 closed 3 years ago
This is expected behaviour, unfortunately. The buffer(0)
trick is just a heuristic that mostly works - but not always. In particular, if the invalidity is caused by a "figure-8"/self-intersection at the highest point of the polygon, then the buffer result keeps the portion of the polygon at the high point - even if that is a very small part of the area. That's whats happening here.
Here's an image of the small area at the top of the polygon which is the buffer(0)
result:
Thinking about this has given me an idea for a further heuristic to counter this situation. If the polygon is flipped along the X axis, then buffer(0)
will return the larger part, which can then be flipped back. To detect that the "wrong" part of the polygon is returned by the first buffer, a couple of heuristics come to mind, such as:
Of course, if the polygon also happens to contain a self-intersection at the bottom, then this won't work. But there are two other transformations that can be tried: flipping along the XY axis, and along the -XY axis. One of these should work except for highly pathological polygons.
Here's an example. A polygon with a top self-intersection produces a non-useful result from buffer(0)
:
Flipping the polygon in X produces the desired result:
I will code this up in a TestBuilder function and post a link to the code.
Meanwhile, I found similar issue in stackoverflow: https://stackoverflow.com/questions/31473553/is-there-a-way-to-convert-a-self-intersecting-polygon-to-a-multipolygon-in-jts
Meanwhile, I found similar issue in stackoverflow: https://stackoverflow.com/questions/31473553/is-there-a-way-to-convert-a-self-intersecting-polygon-to-a-multipolygon-in-jts
Yes, this is a very common problem. Really JTS needs a MakeValid
function similar to the one in GEOS. (Although that also has issues).
The code given in the SO question is fine as far as it goes, but as noted there in a comment it doesn't handle polygons with holes well.
Fixed by #655
I have an isochrone returned by Valhalla:
valhalla-isochrone-json.txt
Since sometimes the geometries are a bit invalid, I use JTS .buffer(0) to clean it.
Initially, it's a big poligon:
POLYGON ((-91.483063 45.088623, -91.482628 45.085438, -91.479324 45.085125, -91.478821 45.082005, -91.47226 45.076057, -91.470383 45.072361, -91.468643 45.071594, -91.465019 45.072636, ...
but the clean version is not ok, nor in shape, nor in location itself
POLYGON ((-91.48652270044593 45.088637411415355, -91.486664 45.088638, -91.486732 45.089169, -91.48652270044593 45.088637411415355))
I'm using jts-core-1.17.1