Snap produces wrong results
I found this bug using ST_Snap on PostGIS and verified with Shapely.
When snapping this input polygon
to this reference polygon using 5 meters tolerance
I'll get this result polygon:
Snap adds that whole extra part and makes the result self intersect. In this case snap should keep the input mostly as is since most of the vertices are already sharing a vertex with the reference geometry.
Geos version: 3.9.0-CAPI-1.16.2
To reproduce the error:
SELECT ST_Snap(
'POLYGON((15.887 21.344,16.875 51.937,18.826 51.616,20.813 51.397,22.81 51.326,24.801 51.479,26.652 52.196,27.457 52.955,28.255 54.769,28.651 57.806,25.469 60.227,31.866 55.133,33.551 54.061,34.673 53.57,38.439 52.23,39.981 51.436,43.286 49.187,44.065 48.648,45.678 47.467,47.18 46.154,48.027 44.373,47.781 42.563,46.84 40.803,45.725 39.143,61.335 40.377,61.248 42.198,60.481 44.037,59.292 45.639,57.69 47.117,54.543 49.584,54.003 50.073,52.641 51.535,51.5 53.173,50.692 54.998,50.402 56.135,50.157 58.118,50.026 60.112,49.901 61.393,49.573 63.365,48.972 65.269,48.284 66.655,47.14 68.293,45.778 69.753,44.246 71.037,42.635 72.113,40.879 73.067,39.081 73.94,38.669 74.135,36.885 75.039,35.201 76.11,33.913 77.627,33.154 79.424,32.463 81.299,31.308 82.906,29.893 83.509,27.904 83.508,26.04 82.821,24.586 81.426,23.739 79.622,23.227 77.691,23.038 76.515,22.543 72.548,22.39 71.536,22.102 69.558,22.005 67.563,22.229 65.625,22.816 63.717,23.796 61.98,24.06 61.641,37.301 82.684,39.292 82.504,41.265 82.19,43.213 81.738,43.879 81.552,47.68 80.309,49.615 79.815,51.606 79.696,53.169 79.973,54.964 80.837,76.177 80.814,77.06 21.639,15.887 21.344))'::geometry,
'POLYGON((15.887 21.344,16.875 51.937,18.826 51.616,20.813 51.397,22.81 51.326,24.801 51.479,26.652 52.196,27.457 52.955,28.255 54.769,28.549 56.746,28.651 57.806,31.866 55.133,33.551 54.061,34.672 53.57,38.439 52.23,39.981 51.436,43.286 49.187,44.065 48.648,45.677 47.467,47.18 46.154,48.027 44.373,47.781 42.563,46.84 40.803,45.725 39.143,61.335 40.377,61.248 42.198,60.481 44.037,59.292 45.639,57.689 47.117,54.543 49.584,54.003 50.073,52.641 51.535,51.499 53.173,50.692 54.998,50.402 56.135,50.157 58.117,50.026 60.112,49.901 61.393,49.573 63.365,48.972 65.269,48.284 66.655,47.14 68.293,45.777 69.753,44.246 71.037,42.636 72.112,40.88 73.067,39.081 73.94,38.669 74.135,36.885 75.039,35.201 76.11,33.913 77.627,33.154 79.424,32.463 81.299,31.308 82.906,37.301 82.684,39.292 82.504,41.265 82.19,43.213 81.738,43.879 81.552,47.68 80.309,49.615 79.815,51.606 79.696,53.169 79.973,54.964 80.837,76.177 80.814,77.06 21.639,15.887 21.344))'::geometry,
5
);
Expected behavior: Each vertex of the input should snap to closest vertex within the tolerance. For each input edge reference vertices within tolerance should be add.
Snapping is essentially heuristic-based code, and doesn't always determine the "right" thing to do. The algorithm needs rework and possibly an entirely new approach.
@dr-jts Are there any plans for a rework of the snapping algorithm in the near future? Or similar coverage cleaning functions.
Are there any plans for a rework of the snapping algorithm in the near future? Or similar coverage cleaning functions.
There is a desire to implement a coverage cleaning/snapping capability. No timeline yet - hopefully this year.
That won't solve this snapping problem, however. Perhaps there will be a chance to looking at the snapping algorithm as well.
@LKajan it looks like your repro has the incorrect output geometry as one input, rather than the input corresponding to the image provided.