ST_LineSubstring
Prev | 8.18. Linear Referencing | Next

## Name

ST_LineSubstring — Returns the part of a line between two fractional locations.

## Synopsis

`geometry ST_LineSubstring(`geometry 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 as fractions of 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.

Availability: 1.1.0, Z and M supported added in 1.1.1

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

This function supports 3d and will not drop the z-index.

## Examples

A LineString seen with 1/3 midrange overlaid (0.333, 0.666)

    SELECT ST_AsText(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_AsText(ST_LineSubstring( 'LINESTRING(25 50, 100 125, 150 190)', 0.333, 0.333));
    ------------------------------------------
     POINT(69.2846934853974 94.2846934853974)

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.

    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_AsText( 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)
        -- skip last i if line length is exact multiple of sublen
        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)

## See Also

ST_Length, ST_LineInterpolatePoint, ST_LineMerge

Prev | Up | Next
ST_LineLocatePoint | Home | ST_LocateAlong