Name

ST_LineLocatePoint — Returns the fractional location of the closest point on a line to a point.

Synopsis

float8 ST_LineLocatePoint(geometry a_linestring, geometry a_point);

float8 ST_LineLocatePoint(geography a_linestring, geography a_point, boolean use_spheroid = true);

Description

Returns a float between 0 and 1 representing the location of the closest point on a LineString to the given Point, as a fraction of 2d line length.

You can use the returned location to extract a Point (ST_LineInterpolatePoint) or a substring (ST_LineSubstring).

This is useful for approximating numbers of addresses

Availability: 1.1.0

Changed: 2.1.0. Up to 2.0.x this was called ST_Line_Locate_Point.

Examples

This example approximates the street number of a house by locating the closest point on a street line. The subquery generates sample house and street data, and ST_DWithin excludes houses that are too far from the street.

Code
SELECT house_loc As as_text_house_loc,
    startstreet_num +
        CAST( (endstreet_num - startstreet_num)
            * ST_LineLocatePoint(street_line, house_loc) As integer) As street_num
FROM
(SELECT 'LINESTRING(1 2,3 4)'::geometry As street_line,
    ST_Point(x*1.01, y*1.03) As house_loc, 10 As startstreet_num,
        20 As endstreet_num
FROM generate_series(1, 3) x CROSS JOIN generate_series(2, 4) As y)
As foo
WHERE ST_DWithin(street_line, house_loc, 0.2);
Output
 as_text_house_loc | street_num
-------------------+------------
 POINT(1.01 2.06)  |         10
 POINT(2.02 3.09)  |         15
 POINT(3.03 4.12)  |         20
Figure
Geometry figure for visual-st-linelocatepoint-01

This example finds the closest point on a line to a point or other geometry.

Code
SELECT ST_LineInterpolatePoint(
    foo.the_line,
    ST_LineLocatePoint(foo.the_line, 'POINT(4 3)'::geometry))
FROM (SELECT 'LINESTRING(1 2,4 5,6 7)'::geometry As the_line) As foo;
Output
POINT(3 4)
Figure
Geometry figure for visual-st-linelocatepoint-02

This example locates the closest segment and point on a LineString.

Code
WITH data AS (
  SELECT
    'LINESTRING (0 0, 10 10, 20 20, 30 30)'::geometry AS line,
    'POINT(15 15.1)'::geometry AS pt
),
segments AS (
  SELECT
    s.i,
    d.pt,
    ST_MakeLine(ST_PointN(d.line, s.i), ST_PointN(d.line, s.i + 1)) AS segment
  FROM data AS d
  CROSS JOIN LATERAL generate_series(1, ST_NumPoints(d.line) - 1) AS s(i)
)
SELECT
  i AS segment_number,
  round(ST_Distance(segment, pt)::numeric, 3) AS distance,
  ST_ClosestPoint(segment, pt) AS closest_point
FROM segments
ORDER BY ST_Distance(segment, pt)
LIMIT 1;
Output
 segment_number | distance |   closest_point
----------------+----------+--------------------
              2 |    0.071 | POINT(15.05 15.05)
Figure
Geometry figure for visual-st-linelocatepoint-03