I have OpenStreetMap data, which represents larger roads (e.g. dual carriageways, aka divided highways) as parallel lines.

The question is answered for ArcGIS or Skeletron here, for example using ESRI's Merge Divided Roads or Collapse Dual Lines to Centerline tools.

Does anyone have suggestions for how to do this within PostGIS? I am working on a server without ArcGIS, and would like to avoid the overhead of transferring the data back and forth across machines.

Update The linked question isn't really answered, and is looking for a solution that is not PostGIS. This should be kept open.

  • 1
    This is close to question gis.stackexchange.com/questions/98165/…
    – user30184
    May 29, 2014 at 6:01
  • 1
    The linked question isn't really answered, and is looking for a solution that is not PostGIS. This should be kept open.
    – dbaston
    May 29, 2014 at 10:22
  • 1
    That's a real stretch to call this question a duplicate. Even without out the recent edit adding not PostGIS, there was nothing mentioning PostGIS in the other question. Or its answers. I'll vote to repopen. May 29, 2014 at 11:00

2 Answers 2


Maybe it's not a very elegant solution and it's based on the method of answering question:https://gis.stackexchange.com/a/295348/120129,

nevertheless, it's one of the variants of solving your question, set up a geoinstrument (for me it's a road with the name "road_border" 11 m wide, type - line (MultiLineString)),

run a simple geoinstrument :-),

      tbla AS (SELECT id, ((ST_DumpPoints(geom)).geom) geom FROM road_border),
      tblb AS (SELECT (ST_Buffer((ST_Dump(geom)).geom, 0.0001)) geom FROM tbla),
      tblc AS (SELECT ST_Centroid(ST_UnaryUnion(Unnest(ST_ClusterWithin(geom, 0.0001)))) geom FROM tblb),
      tbld AS (SELECT ((ST_Dump(ST_DelaunayTriangles(ST_Collect(geom)))).geom) geom FROM tblc),
      tble AS (SELECT (ST_Boundary(geom)) geom FROM ST_Dump((SELECT ST_Polygonize(geom) geom FROM (SELECT ST_Union(geom) geom FROM
      (SELECT ST_ExteriorRing(geom) geom FROM tbld) AS lines) AS foo))),
      tblf AS (SELECT ST_MakeLine(p1, p2) geom FROM (SELECT ST_PointN(geom, generate_series(1, ST_NPoints(geom)-1)) p1,
      ST_PointN(geom, generate_series(2, ST_NPoints(geom))) p2 FROM tble) AS geom),
      tblg AS (SELECT ST_Buffer((ST_Dump(ST_Union(ST_Buffer(geom, 0.0005)))).geom, -0.0005) geom FROM road_border)
      SELECT ST_Intersection (a.geom, b.geom) geom FROM tblf a JOIN tblg b ON ST_Within (a.geom, b.geom);

and see the result.

Good luck to everyone :-),

Original solutions ...

This script is called - ST_RoadAxisFromDelaunayTriangulation...



If you don't want to roll your own function and can put up with a little bit of innacuracy, this might possibly work.

Running ST_ConcaveHull i.e. ST_ConcaveHull(ST_Collect(geom),0.xx) (99% seemed to work as a parameter for my very limited test), then (so long as you have CGAL and SFGCAL compiled or linked to your binary ST_ApproximateMedialAxis would appear to be one way of doing it.

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.