Opened 9 years ago
Closed 7 years ago
#3270 closed defect (fixed)
st_snap() snaps not to closest vertex of the last segment of a closed linestring or polygon
Reported by: | maxbo | Owned by: | pramsey |
---|---|---|---|
Priority: | medium | Milestone: | PostGIS GEOS |
Component: | postgis | Version: | 2.1.x |
Keywords: | st_snap | Cc: |
Description
st_snap(polygon, polygon) behaves not as expected in some cases:
SELECT (du).path, st_astext((du).geom) FROM ( SELECT st_dumppoints(st_snap(a, b, 1)) AS du FROM
(SELECT 'POLYGON (( 3549792.3498 5834172.3803, 3550161.76 5833489.0901, 3548998.3501 5833696.5801, 3549384.15 5833671.1502, 3549601.0899 5833944.12, 3549792.3498 5834172.3803 ))'::geometry AS a,
'POLYGON (( 3549792.3498 5834172.3803, 3549792.3285 5834172.3548, 3549601.0899 5833944.12, 3549384.15 5833671.1502, 3548998.3501 5833696.5801, 3551115 5835384, 3550161.76 5833489.0901, 3549792.3498 5834172.3803 ))'::geometry AS b ) c
)d;
I expected to snap the last segment of polygon a (between POINT(3549601.0899 5833944.12) and POINT(3549792.3498 5834172.3803)) towards POINT(3549792.3285 5834172.3548). So i expected this point to become vertex {1, 6}. Actually, Postgis snaps to this point, but snaps the segment before to the point, which is at much more distance to the point. So the point becomes vertex {1 5}, resulting in an "ugly" geometry.
This is the result of the query. "path" "st_astext"
"{1,1}" "POINT(3549792.3498 5834172.3803)"
"{1,2}" "POINT(3550161.76 5833489.0901)"
"{1,3}" "POINT(3548998.3501 5833696.5801)"
"{1,4}" "POINT(3549384.15 5833671.1502)"
"{1,5}" "POINT(3549792.3285 5834172.3548)"
"{1,6}" "POINT(3549601.0899 5833944.12)"
"{1,7}" "POINT(3549792.3498 5834172.3803)"
The problem only occures when the point should be snapped to the last segment of the polygon. If i shift the start/endpoint of the polygon to the second point, the result of the snapping is correct:
SELECT (du).path, st_astext((du).geom) FROM
( SELECT st_dumppoints(st_snap(a, b, 1)) AS du FROM
(SELECT 'POLYGON (( 3550161.76 5833489.0901, 3548998.3501 5833696.5801, 3549384.15 5833671.1502, 3549601.0899 5833944.12, 3549792.3498 5834172.3803, 3550161.76 5833489.0901 ))'::geometry AS a,
'POLYGON (( 3549792.3498 5834172.3803, 3549792.3285 5834172.3548, 3549601.0899 5833944.12, 3549384.15 5833671.1502, 3548998.3501 5833696.5801, 3551115 5835384, 3550161.76 5833489.0901, 3549792.3498 5834172.3803 ))'::geometry AS b ) c )d;
"path" "st_astext"
"{1,1}" "POINT(3550161.76 5833489.0901)"
"{1,2}" "POINT(3548998.3501 5833696.5801)"
"{1,3}" "POINT(3549384.15 5833671.1502)"
"{1,4}" "POINT(3549601.0899 5833944.12)"
"{1,5}" "POINT(3549792.3285 5834172.3548)"
"{1,6}" "POINT(3549792.3498 5834172.3803)"
"{1,7}" "POINT(3550161.76 5833489.0901)"
Now the POINT(3549792.3285 5834172.3548) is inserted between POINT(3549601.0899 5833944.12) and POINT(3549792.3498 5834172.3803) as {1, 5}.
When i shift the start/endpoint into the other direction, it works fine, too:
SELECT (du).path, st_astext((du).geom) FROM ( SELECT st_dumppoints(st_snap(a, b, 1)) AS du
(SELECT 'POLYGON (( 3549601.0899 5833944.12, 3549792.3498 5834172.3803, 3550161.76 5833489.0901, 3548998.3501 5833696.5801, 3549384.15 5833671.1502, 3549601.0899 5833944.12 ))'::geometry AS a,
'POLYGON (( 3549792.3498 5834172.3803, 3549792.3285 5834172.3548, 3549601.0899 5833944.12, 3549384.15 5833671.1502, 3548998.3501 5833696.5801, 3551115 5835384, 3550161.76 5833489.0901, 3549792.3498 5834172.3803 ))'::geometry AS b ) c )d;
"path" "st_astext"
"{1,1}" "POINT(3549601.0899 5833944.12)"
"{1,2}" "POINT(3549792.3285 5834172.3548)"
"{1,3}" "POINT(3549792.3498 5834172.3803)"
"{1,4}" "POINT(3550161.76 5833489.0901)"
"{1,5}" "POINT(3548998.3501 5833696.5801)"
"{1,6}" "POINT(3549384.15 5833671.1502)"
"{1,7}" "POINT(3549601.0899 5833944.12)"
So the point is inserted again in the right position, this time it is inserted into the first segment after point {1,1} as {1, 2}
The same problem occures for a closed linestring:
SELECT (du).path, st_astext((du).geom) FROM ( SELECT st_dumppoints(st_snap(a, b, 1)) AS du FROM
(SELECT 'LINESTRING ( 3549792.3498 5834172.3803, 3550161.76 5833489.0901, 3548998.3501 5833696.5801, 3549384.15 5833671.1502, 3549601.0899 5833944.12, 3549792.3498 5834172.3803 )'::geometry AS a,
'LINESTRING ( 3549792.3498 5834172.3803, 3549792.3285 5834172.3548, 3549601.0899 5833944.12, 3549384.15 5833671.1502, 3548998.3501 5833696.5801, 3551115 5835384, 3550161.76 5833489.0901, 3549792.3498 5834172.3803 )'::geometry AS b ) c
)d;
"path" "st_astext"
"{1}" "POINT(3549792.3498 5834172.3803)"
"{2}" "POINT(3550161.76 5833489.0901)"
"{3}" "POINT(3548998.3501 5833696.5801)"
"{4}" "POINT(3549384.15 5833671.1502)"
"{5}" "POINT(3549792.3285 5834172.3548)"
"{6}" "POINT(3549601.0899 5833944.12)"
"{7}" "POINT(3549792.3498 5834172.3803)"
But it snaps correctly, when the linestring is not closed (by dropping the first point...)
SELECT (du).path, st_astext((du).geom) FROM ( SELECT st_dumppoints(st_snap(a, b, 1)) AS du FROM
(SELECT 'LINESTRING ( 3550161.76 5833489.0901, 3548998.3501 5833696.5801, 3549384.15 5833671.1502, 3549601.0899 5833944.12, 3549792.3498 5834172.3803 )'::geometry AS a,
'LINESTRING ( 3549792.3285 5834172.3548, 3549601.0899 5833944.12, 3549384.15 5833671.1502, 3548998.3501 5833696.5801, 3551115 5835384, 3550161.76 5833489.0901, 3549792.3498 5834172.3803 )'::geometry AS b ) c
)d;
"path" "st_astext"
"{1}" "POINT(3550161.76 5833489.0901)"
"{2}" "POINT(3548998.3501 5833696.5801)"
"{3}" "POINT(3549384.15 5833671.1502)"
"{4}" "POINT(3549601.0899 5833944.12)"
"{5}" "POINT(3549792.3285 5834172.3548)"
"{6}" "POINT(3549792.3498 5834172.3803)"
So maybe this could be fixed by checking, if st_snap handles a segment near the endpoint different?
I am using
select PostGIS_Full_Version();
POSTGIS="2.1.2 r12389" GEOS="3.4.2-CAPI-1.8.2 r3921" PROJ="Rel. 4.8.0, 6 March 2012" GDAL="GDAL 1.10.1, released 2013/08/26" LIBXML="2.9.1" LIBJSON="UNKNOWN" TOPOLOGY RASTER
Change History (3)
comment:1 by , 9 years ago
Milestone: | PostGIS 2.1.9 → PostGIS GEOS |
---|
comment:2 by , 9 years ago
Thanks for the hint. I wrote a ticket for GEOS with a simpler example. https://trac.osgeo.org/geos/ticket/758
If you could file a ticket for GEOS, that would increase the likelihood of a fix, as the core code for this is in GEOS: http://trac.osgeo.org/geos