-
Notifications
You must be signed in to change notification settings - Fork 365
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Reducing precision results in empty polygon unnecessarily (GEOSGeom_setPrecision) #1058
Comments
This is because the algorithm used to reduce precision actually snap-rounds all vertices and edges to a grid with the specified precision. In this case that causes the longer line to snap to the nearby vertex, and thus effectively collapse the polygon. I agree this behaviour seems a bit counter-intuitive. I'm not sure it's possible to change it, at least not using the current approach. And in fact it might be that trying to come up with an approach to change this result might produce unwanted results in other situations. |
So it's the line that snaps? Because the vertices itself, |
Got it. Thanks for the explanation! |
If you would change this behaviour, please make it configurable, as I use this a lot to clean up slivers and almost dangling nodes after applying overlay operations... |
Good to know there is a clear use case for this behaviour. No plans to change anything at this time, but if we do then we will provide an option. |
Thanks for the explanation @dr-jts -- this result is counter intuitive to me (hence the original shapely issue), but we also share the use case mentioned by @theroggy so it might actually be a good thing now we know how it works! Is there a reference you can point to for the algorithm that is implemented in GEOS/JTS? Or is this one of your own creation? I'd like to go deeper and try and build out some visual documentation. |
Looking at the cgal docs and they distinguish between snap rounding and iterated snap rounding with a nice picture to show the difference. https://doc.cgal.org/latest/Snap_rounding_2/index.html Am I correct in understanding your comment above that GEOS is implementing ISR so any edge that crosses a hot pixel has a node added at that pixel? That would explain why as the polygon gets a bigger aspect ratio it collapses to a single line/empty polygon. |
That's a good reference. The original papers are ok too (although they leave out a few small but key details).
No, there is no iteration in the GEOS algorithm. It uses standard snap-rounding. |
The concept of snap-rounding is explained fairly well in the CGAL docs mentioned above: https://doc.cgal.org/latest/Snap_rounding_2/index.html The original papers are available online as well, e.g.
There's still quite a bit of details that need to be added to get a fully functioning, performant algorithm. The only reference for those is the code. |
This makes a lot of sense now, thank you! For those who see this in the future, the following plot helped me in this particular case. You can see in the latter two columns, the hypotenuse intersects with a hot pixel -- snap rounding then turns the hypotenuse into a polyline with a vertex at that hot pixel, and thus the polygon collapses to zero area. import matplotlib.pyplot as plt
import numpy as np
import shapely
fig, axes = plt.subplots(ncols=4, figsize=(10, 20))
for i, ax in zip(range(3, 7), axes, strict=True):
background = np.zeros((7, 3), dtype=np.uint8)
p = shapely.Polygon([(1,0), (0, i), (1, 3), (1,0)])
for x, y in p.exterior.coords:
background[int(y), int(x)] = 255
ax.imshow(background, cmap='gray')
ax.plot(*p.exterior.xy, color='red', linewidth=2, marker='o')
ax.set_aspect('equal')
ax.set_title(f'Collapses? {shapely.set_precision(p, 1).is_empty}')
plt.show()
plt.close(fig) |
Documentation wise, for a while now there has been a PR in the works to document (amongst others) this behaviour in the shapely docs: https://github.com/shapely/shapely/pull/1964/files Possibly the info in this thread can offer info to further finetune this PR. Not sure which level of detail is expected/wanted in the shapely docs. |
Original report: shapely/shapely#2025
Reproducer with
geosop
using latest main:In this case, it seems the precision of 1.0 should be able to perfectly preserve the input geometry, however an empty polygon is returned. Is there an explanation for why this would be the expected result, or is that a bug?
The KeepCollapsed version also results in an empty polygon, but Pointwise preserves the input:
The text was updated successfully, but these errors were encountered: