I want to create non-overlapping polygon layer from center line by applying the buffer to line layer in postgis. I am able to create polygon layer but how to avoid or resolve overlapped polygons.

select gid,st_multi(ST_union(ST_BUFFER(geom,10,'endcap=flat join=round'))) from roads group by gid

Using this query I am able to create polygon which is overlap at intersection overlap polygon at intersection
Due to 10 meter buffer distance polygon overlaps how to avoid or resolve this expected output
I need expected output as non overlapping polygon with "gid" attribute. Any suggestion will always welcome. Thanks,Amit

  • What sort of behavior do you want the non-overlapping polygons to have? i.e. should they simply expand as normal until they touch and then stop expanding?
    – Conor
    Commented Oct 7, 2013 at 22:45
  • Hi conor, yes i want polygon expand up to touch not overlap. As display in second image, i want 4 separate polygon touch at center not overlap.
    – Amit
    Commented Oct 8, 2013 at 5:05

3 Answers 3


If you don't have primary-secondary attribution to help you, you can still implement some basic logic to decide who's on the losing end of ST_Difference. For example, at a T-shaped intersection, you might specify that the road that passes through the intersection will retain its buffer, while the road that ends at the intersection will have its buffer clipped.

To start, it would be helpful to have a function to express the "passes through tee" relationship. We can say that A passes through the A-B tee if:

  • A intersects B
  • The intersection of A and B is an endpoint of B
  • The intersection of A and B is not an endpoint of A

Turning this logic into a function:

CREATE OR REPLACE FUNCTION passes_through_tee(geom_a geometry, geom_b geometry)
RETURNS boolean AS
SELECT  ST_Contains(endpoints(geom_b), ST_Intersection(geom_a, geom_b)) 
AND NOT ST_Contains(endpoints(geom_a), ST_Intersection(geom_a, geom_b))
$$ language 'sql';

However, endpoints isn't a PostGIS function, so we need to write it:

CREATE OR REPLACE FUNCTION endpoints(g geometry)
RETURNS geometry AS
SELECT ST_Union(endpoints) FROM
  (SELECT ST_Collect(ST_EndPoint(geom), ST_StartPoint(geom)) AS endpoints 
      (SELECT (ST_Dump(g)).geom) dump) subquery
$$ language 'sql';

Note that the ST_Dump subquery allows the function to work on MultiLineString geometries.

To apply these functions to our roads, we can first save the buffered geometries in a temporary table:

  SELECT gid, geom, ST_Buffer(geom, 0.0001, 'endcap=flat join=round') as buffered_geom
  FROM roads;

Then, to pull out the clipped buffers:

SELECT gid, ST_Difference(buffered_geom, 
    (SELECT ST_Union(buffered_geom) FROM buffers b 
      WHERE ST_Intersects(a.geom, b.geom)
        AND a.gid != b.gid
         AND CASE WHEN passes_through_tee(a.geom, b.geom) THEN FALSE 
                  WHEN passes_through_tee(b.geom, a.geom) THEN TRUE                  
                  ELSE a.gid < b.gid END
     ), 'POLYGON EMPTY'::geometry)) 
FROM buffers a

Some example output from this query is below: Example Output

A couple of notes on the above:

  • If we don't have a T-intersection (think end-to-end or four-way intersections) we fall back on gid to pick a winner.
  • The COALESCE function substitutes POLYGON EMPTY for a null value, so that we get our original geometry back if there is nothing to clip against.
  • Polygons will still overlap in cases where the buffers of two roads intersect but the roads themselves do not. This behaviour could be changed, but substituting buffered_geom for geom in the ST_Intersects call.

Do your centerlines have an attribute such as Primary road, Secondary road? If so, the Primary Road (the road almost horizontal)) buffer looks correct. You only need to erase or apply St_Difference to the Secondary buffers. This will remove the portion of the Secondary buffers that overlap the Primary buffer. You probably have intersections of 2 secondary roads, no primary. I'm unsure what logic you might use in this case.

  • Hi klewis , Thanks for quick reply. But i dont have primary or secondary road attribute it only contains details of road like name,description , etc . is there any other way you know, which will help me to process data.
    – Amit
    Commented Oct 8, 2013 at 5:31

As @klewis say, you can use an attribute such as "road order". When not have it, you can create with the method of this answer (ncolors attribute) and calculate order by "river order" method,

enter image description here

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.