Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

I'm looking for a way to create so-called one-sided buffers or parallel lines in PostGIS. Example: 1. buffer, 2. one-side, 3. both-sides

alt text

I've found some discussion on the mailing list from 2009 and information that it has been implemented in GEOS, but nothing about the current PostGIS status.

In case the function is not implemented yet, do you know any workarounds? Is it possible to cut off one side of a normal buffer?

share|improve this question
    
So you're looking for an equivalent to "offset" in AutoCAD? –  dassouki Aug 15 '10 at 23:06
    
@dassouki: Sorry, I don't know AutoCAD. But I think UMN Mapserver has an "offset" option that would do what I'm looking for. –  underdark Aug 17 '10 at 10:11
    
How to create one-sided buffers or parallel lines, from a table that have 600 lines? –  user3230 Jun 10 '11 at 0:35
    
Welcome to the site. If the current set of answers doesn't solve your problem you should open this as a new question (and state why this question does not answer your problem). Within the format of the site this is not an appropriate place to make this statement, as it is not an answer to the question. –  Andy W Jun 10 '11 at 1:26
    
How can I create a parallel lines in a MULTILINESTRING table? –  Felipe Costa Jun 23 '11 at 13:35
add comment

4 Answers 4

up vote 10 down vote accepted

Proper one-sided buffers were supposed to have landed in 1.5, but it looks to me that while the styles did land, sidedness didn't make it in. There is however a current patchset which exposes GEOSSingleSidedBuffer and performs the one-sided buffer as expected, under the name ST_OffsetCurve; see further background in ticket #413. In use:

select ST_AsText(ST_OffsetCurve(
ST_GeomFromText('LINESTRING(10 10,10 20, 20 20 )'),
1,'right', 'join=mitre mitre_limit=5.0'));
--------------
LINESTRING(20 19,11 19,11 10)
share|improve this answer
add comment

This sample creates two polygons on either side of a linestring. It requires PostGIS 1.5 or greater. I'm not sure how well it will cope with lines that cross themselves.

SELECT ST_AsText(geom)

FROM ST_Dump ((

SELECT 
  ST_Polygonize(GEOMUNION(ST_Boundary(ST_Buffer(the_geom, 0.5, 'endcap=flat join=round')), the_geom)) AS buffer_sides 
FROM
  (SELECT ST_GeomFromText('LINESTRING(1 1, 1 5, 5 5)') AS the_geom) AS table1

));

It outputs:

                        st_astext

------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------
 POLYGON((0.5 5,0.509607359798385 5.09754516100806,0.538060233744357 5.19134171618254,0.584265193848727 5.2777851165098,
0.646446609406726 5.35355339059327,0.722214883490199 5.41573480615127,0.808658283817455 5.46193976625564,0.9024548389919
36 5.49039264020162,1 5.5,5 5.5,5 5,1 5,1 1,0.5 1,0.5 5))
 POLYGON((5 5,5 4.5,1.5 4.5,1.5 1,1 1,1 5,5 5))
(2 rows)

The code works the following way:

  1. Buffer the linestring using ST_Buffer. We take advantage of the PostGIS 1.5 feature supporting custom endcaps in order to specify no end cap at all. See example below.
  2. Split the buffered polygon in two, using the original line, using the method documented in the wiki.

This could be improved to cope with self-crossing lines in future.

A buffered linestring with a flat endcap

share|improve this answer
add comment

This modification creates two parallel linestring. It requires PostGIS 1.5 or greater.

required geometry or wkt, and distance in the buffer


SELECT astext(
     st_removepoint( 
     st_removepoint(        st_linemerge(ST_Difference(st_boundary(geom),ST_GeomFromText('LINESTRING(1 1, 1 5, 5 5)')))         ,0),
      st_npoints(st_linemerge(ST_Difference(st_boundary(geom),ST_GeomFromText('LINESTRING(1 1, 1 5, 5 5)'))))-2)

    ) as parallel
    FROM ST_Dump ((
    SELECT 
    ST_Polygonize(st_union(ST_Boundary(ST_Buffer(geometria, 0.5, 'endcap=flat join=mitre mitre_limit=5.0')), geometria)) AS buffer_sides 
    FROM
    (SELECT ST_GeomFromText('LINESTRING(1 1, 1 5, 5 5)') 
        AS geometria) AS tabla))

-------------- RESULTS

"LINESTRING(0.5 1,0.5 5.5,5 5.5)"
"LINESTRING(5 4.5,1.5 4.5,1.5 1)"

share|improve this answer
add comment

Because i still can't comment here, i add this answer

SCW give the best answer,

select ST_AsText(ST_OffsetCurve(
ST_GeomFromText('LINESTRING(10 10,10 20, 20 20 )'),
1, 'right', 'join=mitre mitre_limit=5.0'));
--------------
LINESTRING(20 19,11 19,11 10)

But looks like the function change
http://postgis.refractions.net/docs/ST_OffsetCurve.html

Now the 'right' parameter isn't necessary. Using positive distance will create left side and negative distance will create the right side

Also no patch needed with my postgis

SELECT PostGIS_full_version();
"POSTGIS="2.0.3 r11132" GEOS="3.3.8-CAPI-1.7.8" 
PROJ="Rel. 4.8.0, 6 March 2012" GDAL="GDAL 1.9.2, 
released 2012/10/08" LIBXML="2.7.8" LIBJSON="UNKNOWN" RASTER"
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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