Wednesday, March 25, 2009

Problem with PostGIS ST_Buffer

Seems like I'm not getting back all of the geometry from a query.

select name, Buffer(the_geom, .12) from coastlines where iso_3_code = 'PNG';



After a bit of screwing around, the solution I found is to blow up the MULTIPOLYGON that is Papua New Guinea with ST_Dump, then ST_Buffer each of the individual polygons, and finally return those buffered polygons as a subquery result to the geomunion function. Like this:

SELECT c.name, geomunion(the_geom) FROM (SELECT name, ST_Buffer((ST_Dump(the_geom)).geom, .12) AS the_geom FROM coastlines) c WHERE c.name LIKE 'Papua%' GROUP BY c.name;

The results look like this:


Works, but it doesn't seem like this should be necessary.

1 comments:

Dan Stahlke said...

Papua New Guinea crosses the dateline (a.k.a. antimeridian). Now, postgis should not be aware of the meanings of the coordinates in a geometry column so the fact that it goes near a dateline shouldn't matter. I suspect that the problem may be that the original data has been clipped to the 180 longitude line and this has introduced a degenerate segment. I am getting a similar problem in the Aleutian islands on a polygon that butts up against 180 degrees. Also a pair of nearby polygons that touch -170 degrees disappear as well, but I have no theory here. Hopefully this sheds a tiny bit of light on why st_buffer(?, 0) is doing this.

From your picture it appears that you are using a projection that properly crosses the dateline. If on the other hand you had stored your polygon in geographic coordinates, without chopping the island into two polygons (one for eastern hemisphere and one for western) then you would have a line segment going from -180 to 180. In geographic projection your polygon would be in bad shape (it would almost certainly have self intersections) and st_buffer would be correct in discarding it.