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)

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
    Commented Jun 13, 2016 at 9:39
  • ST_MakeValid could also work ...
    – WKT
    Commented Jun 13, 2016 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
    Commented Jun 13, 2016 at 9:48
  • ST_ConcaveHull ?
    – WKT
    Commented Jun 13, 2016 at 9:52
  • See also gis.stackexchange.com/questions/173977/…
    – dbaston
    Commented Jun 13, 2016 at 12:18

2 Answers 2


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;


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;

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(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.

  • Hi, where can I find some explanation in the docu about what mitre and mitre_limit do?
    – Momchill
    Commented Jan 17, 2023 at 16:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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