# Linear Referencing

ST_LineInterpolatePoint

Returns a point interpolated along a line at a fractional location.

    				geometry ST_LineInterpolatePoint
    				geometry  a_linestring
    				float8  a_fraction

                    geography ST_LineInterpolatePoint
                    geography  a_linestring
                    float8  a_fraction
                    boolean use_spheroid = true

### Description

Returns a point interpolated along a line at a fractional location. First argument must be a LINESTRING. Second argument is a float between 0 and 1 representing the fraction of line length where the point is to be located. The Z and M values are interpolated if present.

See ST_LineLocatePoint for computing the line location nearest to a Point.

This function computes points in 2D and then interpolates values for Z and M, while ST_3DLineInterpolatePoint computes points in 3D and only interpolates the M value.

Since release 1.1.1 this function also interpolates M and Z values (when present), while prior releases set them to 0.0.

Availability: 0.8.2, Z and M supported added in 1.1.1

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

&Z_support;

### Examples

This example returns the point 20 percent along a line.

    SELECT ST_LineInterpolatePoint(
    'LINESTRING(25 50,100 125,150 190)',
    0.2);

    POINT(51.5974135047432 76.5974135047432)

The mid-point of a 3D line:

    SELECT ST_LineInterpolatePoint(
    'LINESTRING(1 2 3,4 5 6,6 7 8)',
    0.5);

    POINT(3.5 4.5 5.5)

The closest point on a line to a point:

    SELECT ST_LineInterpolatePoint(
        line.geom,
        ST_LineLocatePoint(line.geom, 'POINT(4 3)'))
    FROM (SELECT 'LINESTRING(1 2,4 5,6 7)'::geometry As geom) AS line;

    POINT(3 4)

An interpolated point can be offset to the left or right of a line by using ST_OffsetCurve before interpolation. This is useful for locating an address point beside a street centerline.

    WITH street AS (
        SELECT 'LINESTRING(0 0, 10 0)'::geometry AS geom,
               100 AS from_num,
               200 AS to_num
    )
    SELECT
        ST_LineInterpolatePoint(
            ST_OffsetCurve(geom, -2),
            (160 - from_num)::float8 / (to_num - from_num)
        ) AS interpolated_offset_point
    FROM street;

     interpolated_offset_point
    ---------------------------
     POINT(6 -2)

### See Also

ST_LineInterpolatePoints, ST_3DLineInterpolatePoint, ST_LineLocatePoint, ST_OffsetCurve

ST_3DLineInterpolatePoint

Returns a point interpolated along a 3D line at a fractional location.

    				geometry ST_3DLineInterpolatePoint
    				geometry  a_linestring
    				float8  a_fraction

### Description

Returns a point interpolated along a 3D line at a fractional location. First argument must be a LINESTRING. Second argument is a float between 0 and 1 representing the point location as a fraction of line length. The M value is interpolated if present.

ST_LineInterpolatePoint computes points in 2D and then interpolates the values for Z and M, while this function computes points in 3D and only interpolates the M value.

Availability: 3.0.0

&Z_support;

### Examples

Return point 20% along 3D line

    SELECT ST_3DLineInterpolatePoint(
    'LINESTRING(25 50 70,100 125 90,150 190 200)',
    0.20);

    POINT Z (59.06758929108215 84.06758929108216 79.0846904776219)

### See Also

ST_LineInterpolatePoint, ST_LineInterpolatePoints, ST_LineLocatePoint

ST_LineInterpolatePoints

Returns points interpolated along a line at a fractional interval.

    				geometry ST_LineInterpolatePoints
    				geometry  a_linestring
    				float8  a_fraction
    				boolean  repeat

                    geography ST_LineInterpolatePoints
                    geography  a_linestring
                    float8  a_fraction
                    boolean use_spheroid = true
                    boolean  repeat = true

### Description

Returns one or more points interpolated along a line at a fractional interval. The first argument must be a LINESTRING. The second argument is a float8 between 0 and 1 representing the spacing between the points as a fraction of line length. If the third argument is false, at most one point will be constructed (which is equivalent to ST_LineInterpolatePoint.)

If the result has zero or one points, it is returned as a POINT. If it has two or more points, it is returned as a MULTIPOINT.

Availability: 2.5.0

&Z_support;

&M_support;

### Examples

This example returns points every 20 percent along a two-dimensional line.

    SELECT ST_LineInterpolatePoints(
    'LINESTRING(25 50,100 125,150 190)',
    0.20);

    MULTIPOINT((51.5974135047432 76.5974135047432),(78.1948270094864 103.194827009486),(104.132163186446 130.37181214238),(127.066081593223 160.18590607119),(150 190))

### See Also

ST_LineInterpolatePoint, ST_LineLocatePoint

ST_LineLocatePoint

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

    				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.

    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);

     as_text_house_loc | street_num
    -------------------+------------
     POINT(1.01 2.06)  |         10
     POINT(2.02 3.09)  |         15
     POINT(3.03 4.12)  |         20

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

    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;

    POINT(3 4)

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

    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;

     segment_number | distance |   closest_point
    ----------------+----------+--------------------
                  2 |    0.071 | POINT(15.05 15.05)

### See Also

ST_ClosestPoint, ST_DWithin, ST_Length2D, ST_LineInterpolatePoint, ST_LineSubstring

ST_LineSubstring

Returns the part of a line between two fractional locations.

    				geometry ST_LineSubstring
    				geometry  a_linestring
    				float8  startfraction
    				float8  endfraction

                    geography ST_LineSubstring
                    geography  a_linestring
                    float8  startfraction
                    float8  endfraction

### Description

Computes the line which is the section of the input line starting and ending at the given fractional locations. The first argument must be a LINESTRING. The second and third arguments are values in the range [0, 1] representing the start and end locations. For geometry inputs, the fractions are measured in 2D line length. The Z and M values are interpolated for added endpoints if present.

If `startfraction` and `endfraction` have the same value this is equivalent to ST_LineInterpolatePoint.

This only works with LINESTRINGs. To use on contiguous MULTILINESTRINGs first join them with ST_LineMerge.

Since release 1.1.1 this function interpolates M and Z values. Prior releases set Z and M to unspecified values.

Enhanced: 3.4.0 - Support for geography was introduced.

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

Availability: 1.1.0, Z and M supported added in 1.1.1

&Z_support;

### Examples

Extract the middle third of a LineString, from 0.333 to 0.666.

    SELECT ST_LineSubstring(
    'LINESTRING (20 180,50 20,90 80,120 40,180 150)',
    0.333,
    0.666);

    LINESTRING (45.17311810399485 45.74337011202746, 50 20, 90 80, 112.97593050157862 49.36542599789519)

If start and end locations are the same, the result is a POINT.

    SELECT ST_LineSubstring(
    'LINESTRING(25 50,100 125,150 190)',
    0.333,
    0.333);

    POINT(69.28469348539744 94.28469348539744)

A query to cut a LineString into sections of length 100 or shorter. It uses `generate_series()` with a CROSS JOIN LATERAL to produce the equivalent of a FOR loop.

The final generated step is filtered out when the line length is an exact multiple of the requested section length.

    WITH data(id, geom) AS (VALUES
            ( 'A', 'LINESTRING( 0 0, 200 0)'::geometry ),
            ( 'B', 'LINESTRING( 0 100, 350 100)'::geometry ),
            ( 'C', 'LINESTRING( 0 200, 50 200)'::geometry )
        )
    SELECT id, i,
           ST_LineSubstring(geom, startfrac, LEAST( endfrac, 1 )) AS geom
    FROM (
        SELECT id, geom, ST_Length(geom) len, 100 sublen FROM data
        ) AS d
    CROSS JOIN LATERAL (
        SELECT i, (sublen * i) / len AS startfrac,
                  (sublen * (i+1)) / len AS endfrac
        FROM generate_series(0, floor( len / sublen )::integer ) AS t(i)
        WHERE (sublen * i) / len <> 1.0
        ) AS d2;

     id | i |            geom
    ----+---+-----------------------------
     A  | 0 | LINESTRING(0 0,100 0)
     A  | 1 | LINESTRING(100 0,200 0)
     B  | 0 | LINESTRING(0 100,100 100)
     B  | 1 | LINESTRING(100 100,200 100)
     B  | 2 | LINESTRING(200 100,300 100)
     B  | 3 | LINESTRING(300 100,350 100)
     C  | 0 | LINESTRING(0 200,50 200)

Split a LineString by points by locating the points along the line, adding the 0 and 1 endpoints, and extracting substrings between adjacent locations.

    WITH data AS (
      SELECT 'LINESTRING(0 0, 10 0)'::geometry AS line,
             'MULTIPOINT((2 0),(5 0),(8 0))'::geometry AS points
    ),
    fractions AS (
      SELECT 0.0 AS fraction
      UNION ALL
      SELECT 1.0
      UNION ALL
      SELECT ST_LineLocatePoint(line, (dp).geom)
      FROM data
      CROSS JOIN LATERAL ST_Dump(points) AS dp
    ),
    ordered AS (
      SELECT DISTINCT fraction
      FROM fractions
    ),
    segments AS (
      SELECT fraction AS start_fraction,
             lead(fraction) OVER (ORDER BY fraction) AS end_fraction
      FROM ordered
    )
    SELECT row_number() OVER (ORDER BY start_fraction) AS segment_id,
           ST_LineSubstring(line, start_fraction, end_fraction) AS geom
    FROM data
    CROSS JOIN segments
    WHERE end_fraction IS NOT NULL
      AND start_fraction <> end_fraction
    ORDER BY start_fraction;

     segment_id |         geom
    ------------+----------------------
              1 | LINESTRING(0 0,2 0)
              2 | LINESTRING(2 0,5 0)
              3 | LINESTRING(5 0,8 0)
              4 | LINESTRING(8 0,10 0)

Geography implementation measures along a spheroid, geometry along a line

    SELECT ST_LineSubstring(
    'LINESTRING(-118.2436 34.0522,-71.0570 42.3611)'::geography,
    0.333,
    0.666) AS geog_sub,
    ST_LineSubstring(
        'LINESTRING(-118.2436 34.0522,-71.0570 42.3611)'::geometry,
        0.333,
        0.666) AS geom_sub;

    -[ RECORD 1 ]----------
    geog_sub | LINESTRING(-103.911641 38.931128,-87.941787 41.831072)
    geom_sub | LINESTRING(-102.530462 36.819064,-86.817324 39.585927)

For geometry inputs, the fractional locations are based on the 2D length of the line, even when the input has Z values. The resulting Z values are interpolated along the selected 2D location.

    WITH data AS (
      SELECT 'LINESTRING Z (0 0 0,0 2 5,0 10 10)'::geometry AS geom
    )
    SELECT ST_Length(geom) AS length_2d,
           ST_3DLength(geom) AS length_3d,
           ST_LineSubstring(geom, 0, 0.5) AS substring
    FROM data;

     length_2d |    length_3d     |              substring
    -----------+------------------+-------------------------------------
            10 | 14.819145939191106 | LINESTRING Z (0 0 0,0 2 5,0 5 6.875)

### See Also

ST_Length, ST_LineExtend, ST_LineInterpolatePoint, ST_LineLocatePoint, ST_LineMerge, ST_Split

ST_LocateAlong

Returns the point(s) on a geometry that match a measure value.

    			geometry ST_LocateAlong
    			geometry  geom_with_measure
    			float8  measure
    			float8  offset = 0

### Description

Returns the location(s) along a measured geometry that have the given measure values. The result is a Point or MultiPoint. Polygonal inputs are not supported.

If `offset` is provided, the result is offset to the left or right of the input line by the specified distance. A positive offset will be to the left, and a negative one to the right.

Use this function only for linear geometries with an M component

The semantic is specified by the ISO/IEC 13249-3 SQL/MM Spatial standard.

Availability: 1.1.0 by old name ST_Locate_Along_Measure.

Changed: 2.0.0 in prior versions this used to be called ST_Locate_Along_Measure.

&M_support;

&sqlmm_compliant; SQL-MM IEC 13249-3: 5.1.13

### Examples

    SELECT ST_LocateAlong(
    'MULTILINESTRINGM((1 2 3, 3 4 2, 9 4 3),(1 2 3, 5 4 5))'::geometry,
    3);

    MULTIPOINT M ((1 2 3),(9 4 3),(1 2 3))

### See Also

ST_LocateBetween, ST_LocateBetweenElevations, ST_InterpolatePoint

ST_LocateBetween

Returns the portions of a geometry that match a measure range.

    			geometry ST_LocateBetween
    			geometry  geom
    			float8  measure_start
    			float8  measure_end
    			float8  offset = 0

### Description

Return a geometry (collection) with the portions of the input measured geometry that match the specified measure range (inclusively).

If the `offset` is provided, the result is offset to the left or right of the input line by the specified distance. A positive offset will be to the left, and a negative one to the right.

Clipping a non-convex POLYGON may produce invalid geometry.

The semantic is specified by the ISO/IEC 13249-3 SQL/MM Spatial standard.

Availability: 1.1.0 by old name ST_Locate_Between_Measures.

Changed: 2.0.0 - in prior versions this used to be called ST_Locate_Between_Measures.

Enhanced: 3.0.0 - added support for POLYGON, TIN, TRIANGLE.

&M_support;

&sqlmm_compliant; SQL-MM IEC 13249-3: 5.1

### Examples

    SELECT ST_LocateBetween(
    'MULTILINESTRING M ((1 2 3,3 4 2,9 4 3),(1 2 3,5 4 5))'::geometry,
    1.5,
    3);

    GEOMETRYCOLLECTION M (LINESTRING M (1 2 3,3 4 2,9 4 3),POINT M (1 2 3))

Extract the section between measures 2 and 8, offset to the left. Because the clipped line and the offset result share the same coordinate space, this example is intended for a single overlay panel rather than separate side-by-side figures.

    SELECT ST_LocateBetween(
    ST_AddMeasure(
        'LINESTRING (20 180,50 20,100 120,180 20)',
        0,
        10),
    2,
    8,
    20);

    MULTILINESTRING((54.49835 104.53427,58.700561 82.122481,82.111456 128.944272,84.248937 132.324934,87.01637 135.21267,90.303073 137.491987,93.977598 139.071724,97.892984 139.888702,101.892639 139.910247,105.816599 139.135495,109.507928 137.595434,112.818995 135.351657,115.617376 132.493901,145.310173 95.377905))

### See Also

ST_LocateAlong, ST_LocateBetweenElevations

ST_LocateBetweenElevations

Returns the portions of a geometry that lie in an elevation (Z) range.

    			geometry ST_LocateBetweenElevations
    			geometry  geom
    			float8  elevation_start
    			float8  elevation_end

### Description

Returns a geometry (collection) with the portions of a geometry that lie in an elevation (Z) range.

Clipping a non-convex POLYGON may produce invalid geometry.

Availability: 1.4.0

Enhanced: 3.0.0 - added support for POLYGON, TIN, TRIANGLE.

&Z_support;

### Examples

    SELECT ST_LocateBetweenElevations(
    'LINESTRING(1 2 3,4 5 6)'::geometry,
    2,
    4);

    MULTILINESTRING Z ((1 2 3,2 3 4))

    SELECT ST_LocateBetweenElevations(
    'LINESTRING(1 2 6,4 5 -1,7 8 9)',
    6,
    9) As ewelev;

    GEOMETRYCOLLECTION Z (POINT Z (1 2 6),LINESTRING Z (6.1 7.1 6,7 8 9))

### See Also

ST_Dump, ST_LocateBetween

ST_InterpolatePoint

Returns the interpolated measure of a geometry closest to a point.

                float8 ST_InterpolatePoint
                geometry  linear_geom_with_measure
                geometry  point

### Description

Returns an interpolated measure value of a linear measured geometry at the location closest to the given point.

Use this function only for linear geometries with an M component

Availability: 2.0.0

&Z_support;

### Examples

    SELECT ST_InterpolatePoint(
    'LINESTRING M (0 0 0,10 0 20)',
    'POINT(5 5)');

    10

### See Also

ST_AddMeasure, ST_LocateAlong, ST_LocateBetween

ST_3DInterpolatePoint

Returns the interpolated measure of a geometry closest to a point in 3D.

                float8 ST_3DInterpolatePoint
                geometry  linear_geom_with_measure
                geometry  point

### Description

Returns the interpolated measure value of a linear ZM geometry at the location closest to the given point, using 3D (XYZ) distance for the projection. Use this function when the geometry has significant Z variation, such as flight trajectories, where ST_InterpolatePoint would give incorrect results by ignoring the Z dimension.

The line must have both Z and M dimensions. The point should have a Z dimension.

Availability: 3.7.0

&Z_support;

### Examples

This example interpolates on a line rising diagonally in Z, using a point at the 3D midpoint.

    SELECT ST_3DInterpolatePoint(
    'LINESTRING ZM (0 0 0 0,10 0 10 20)',
    'POINT Z (5 0 5)');

    10

This example uses a vertical line with zero XY extent, where 3D projection works but 2D projection does not.

    SELECT ST_3DInterpolatePoint(
    'LINESTRING ZM (0 0 0 0,0 0 10 100)',
    'POINT Z (5 5 5)');

    50

### See Also

ST_InterpolatePoint, ST_AddMeasure, ST_LocateAlong, ST_LocateBetween

ST_AddMeasure

Interpolates measures along a linear geometry.

    			geometry ST_AddMeasure
    			geometry  geom_mline
    			float8  measure_start
    			float8  measure_end

### Description

Return a derived geometry with measure values linearly interpolated between the start and end points. If the geometry has no measure dimension, one is added. If the geometry has a measure dimension, it is over-written with new values. Only LINESTRINGS and MULTILINESTRINGS are supported.

Availability: 1.5.0

&Z_support;

### Examples

    SELECT ST_AddMeasure(
    'LINESTRING(1 0,2 0,4 0)',
    1,
    4) As ewelev;

    LINESTRING M (1 0 1,2 0 2,4 0 4)

    SELECT ST_AddMeasure(
    'LINESTRING(1 0 4,2 0 4,4 0 4)',
    10,
    40) As ewelev;

    LINESTRING ZM (1 0 4 10,2 0 4 20,4 0 4 40)

    SELECT ST_AddMeasure(
    'LINESTRINGM(1 0 4, 2 0 4, 4 0 4)',
    10,
    40) As ewelev;

    LINESTRING M (1 0 10,2 0 20,4 0 40)

    SELECT ST_AddMeasure(
    'MULTILINESTRINGM((1 0 4, 2 0 4, 4 0 4),(1 0 4, 2 0 4, 4 0 4))',
    10,
    70) As ewelev;

    MULTILINESTRING M ((1 0 10,2 0 20,4 0 40),(1 0 40,2 0 50,4 0 70))