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 pramsey, 9 years ago

Milestone: PostGIS 2.1.9PostGIS GEOS

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

comment:2 by maxbo, 9 years ago

Thanks for the hint. I wrote a ticket for GEOS with a simpler example. https://trac.osgeo.org/geos/ticket/758

comment:3 by pramsey, 7 years ago

Resolution: fixed
Status: newclosed

GEOS issue is closed

Note: See TracTickets for help on using tickets.