wiki:UsersWikiLinearRefFunctions

Functions for Linear Referencing

These functions augment the built-in ones in PostGIS.

ST_LineLocateSegment

Locates the segment on a line containing the location closest to a given point. This can be useful for inserting a line vertex at the location closest to a given point.

Also see ST_Snap for doing this in a single step, and with the ability to add multiple points.

--- ST_LineLocateSegment: Locates the segment on a LineString containing the location closest to a given point. 
--- Returns a record containing:
---   index: the segment index of the closest point on the line
---   dist: the distance to the given point
---   geom: the closest point on the line

CREATE OR REPLACE FUNCTION ST_LineLocateSegment( line geometry, pt geometry )
RETURNS table(index integer, dist double precision, geom geometry)
AS $$
  WITH segs AS (
    SELECT s.i, ST_MakeLine( ST_PointN( line, s.i ), ST_PointN( line, s.i+1 ) ) AS seg
        FROM generate_series(1, ST_NumPoints( line )-1) AS s(i)
  ),
  dist AS (
    SELECT i, ST_Distance(seg, pt) AS dist, ST_ClosestPoint(seg, pt) AS geom
      FROM segs
      ORDER BY dist
      LIMIT 1
  )
  SELECT i - 1, dist, geom FROM dist;
$$
LANGUAGE sql STABLE STRICT;

Example 1: show the segment record returned

SELECT ST_LineLocateSegment( 'LINESTRING (0 0, 10 10, 20 20, 30 30)'::geometry,
  'POINT(15 15.1)'::geometry);

Example 2: Add the closest point to the line

  • Note that the ST_LineLocateSegment function in the JOIN can reference the preceding table in the join (functions cause an implicit LATERAL join).
WITH data(id, line) AS (VALUES
    ( 1, 'LINESTRING (0 0, 10 10, 20 20, 30 30)'::geometry )
)
SELECT id, ST_AddPoint( data.line, geom, index )
  FROM data CROSS JOIN ST_LineLocateSegment( data.line, 'POINT(15 15.1)'::geometry );
Last modified 12 months ago Last modified on Aug 5, 2020, 2:46:04 PM