7

I try to delete the slivers that appeared when I have merged some polygons.

I have two different cases:enter image description here

For the CASE 1, no problem I fill the gap with:

CREATE OR REPLACE FUNCTION sliver_killer(geometry,float) RETURNS geometry AS
$$ SELECT ST_BuildArea(ST_Collect(a.geom)) as final_geom
FROM ST_DumpRings($1) AS a
WHERE a.path[1] = 0 OR
(a.path[1] > 0 AND ST_Area(a.geom) > $2)
$$
LANGUAGE 'sql' IMMUTABLE;

UPDATE merged SET geom = sliver_killer(geom,50::float);

A function that fill all the gaps smaller than x square meter.

BUT for the CASE 2, when the small gaps are "open" I can't manage to fill those gaps.

I have try something like: buffer(1) followed by buffer(-1) but of course I obtain some rounded corners. Did someone have a true solution ?

  • did you try buffer(0) ? – WKT Jun 13 '16 at 9:39
  • ST_MakeValid could also work ... – WKT Jun 13 '16 at 9:44
  • @WKT the problem is that the sliver is just bigger than the tolerance and the geometry is perfecly valid (no self intersection, nothing like that) – obchardon Jun 13 '16 at 9:48
  • ST_ConcaveHull ? – WKT Jun 13 '16 at 9:52
  • See also gis.stackexchange.com/questions/173977/… – dbaston Jun 13 '16 at 12:18
4

Ok I found an answer:

You can avoid to get rounded corner by adding the parameter 'join=mitre' to st_buffer:

So it work perfectly fine with:

SELECT st_buffer(st_buffer(geom,1,'join=mitre'),-1,'join=mitre') FROM mygeotable;

EDIT

If the buffer is too large st_buffer(geom,10,'join=mitre') produce from time to time some strange results (the polygones become spiky). So to avoid this effect it's safer to preserve the old boundary with st_intersection:

SELECT st_intersection(st_buffer(st_buffer(geom,-1,'join=mitre'),1,'join=mitre'),geom) FROM mygeotable;
0

The ST_Buffer solution already explained here is valid, but it can be improved in order to avoid the spikes (and the intersection step itself). You need to add a new parameter to the buffer mitre_limit.

SELECT st_intersection(
          st_buffer(
             st_buffer(geom, 1, 'join=mitre mitre_limit=1.0'
          ), -1, 'join=mitre mitre_limit=1.0'
        ), geom) as
FROM _mygeotable_ ;

This way you will get what you want much easier and cleaner.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.