[GIS] Extending a linestring to the edge of an enclosing polygon in PostGIS

geometrylinestringpostgis

I have linestrings that are each entirely within a polygon. I want to extend the first and last segments to touch the first rings of the polygon in line with them.

Example

Best Answer

I'm sure it could be prettier but I came up with getting the first and last segments, scaling them about the inner end of the segment so they are as long as the diagonal of the bounding box of the polygon then intersecting with the boundary of the polygon and selecting the points closest to the line endpoints then combining those new points with the existing linestring to give a new linestring.

select *, 
  (select ST_MakeLine(geom) from
  ((select array[0] as path, geom from ST_Dump(ST_Intersection(boundary, ST_Scale(first_segment, ST_MakePoint(dist/ST_length(first_segment), dist/ST_length(first_segment)), ST_EndPoint(first_segment)))) order by ST_Distance(geom, ST_StartPoint(first_segment)) limit 1)
  union all
  select * from ST_Dump(line)
  union all
  (select array [ST_NumPoints(line)+1] as path, geom from ST_Dump(ST_Intersection(boundary, ST_Scale(last_segment, ST_MakePoint(dist/ST_length(last_segment), dist/ST_length(last_segment)), ST_StartPoint(last_segment)))) order by ST_Distance(geom, ST_StartPoint(last_segment)) limit 1)) as points
)
from
  (select area, line, 
    ST_Length(ST_BoundingDiagonal(area)) as dist,
    (select st_makeline(geom) from ST_DumpPoints(line) where path in (array[1],array[2])) as first_segment,
    (select st_makeLine(geom) from ST_DumpPoints(line) where path in (array[ST_NPoints(line)],array[ST_NPoints(line)-1])) as last_segment,
    ST_Boundary(area) as boundary
    from (values ('POLYGON((-10 -25, -15 15, 20 20, 22 -10, -10 -25))'::geometry,'LINESTRING(-7 -10, -5 -2, 6 7, 15 8)'::geometry)) as t(area,line)) as parts