Skip to content

Instantly share code, notes, and snippets.

@dbaston
Last active January 24, 2017 14:06
Show Gist options
  • Save dbaston/d909424cf0ddf388b04627fa1c045ed6 to your computer and use it in GitHub Desktop.
Save dbaston/d909424cf0ddf388b04627fa1c045ed6 to your computer and use it in GitHub Desktop.
-- Divide an input geometry into equal-length portions of the specified length.
-- The final segment will contain the "unused" portion of the line and will be
-- shorter than the others.
--
-- Note that segment_length is in the units of the geometry's coordinate system,
-- i.e. degrees for 4326. To use the function with geographic coordinates and
-- a distance in meters, it is recommended to project the geometry into a
-- planar coordinate system, e.g. using _ST_BestSRID.
CREATE OR REPLACE FUNCTION pg_temp.DivideLine(g geometry, segment_length double precision)
RETURNS SETOF geometry AS $$
SELECT ST_LineSubstring($1,
i*$2/length_m,
LEAST(1.0, (i+1)*$2/length_m))
FROM (SELECT $1, ST_Length($1) AS length_m) sq
CROSS JOIN LATERAL generate_series(0, floor(length_m / $2)::int) AS i
$$ LANGUAGE SQL;
@dbaston
Copy link
Author

dbaston commented Jan 24, 2017

Note that the pg_temp in the function definition creates this function in a temporary schema, so it goes away at the end of your session. If you want the function to persist in the database, remove pg_temp (and optionally replace it with another schema.)

Example usage:
Given a table "hydro" with ID and geometry:

                Table "public.hydro"
 Column |              Type              | Modifiers 
--------+--------------------------------+-----------
 gid    | integer                        | 
 geom   | geometry(MultiLineString,4269) | 

To temporarily project the coordinates to a planar system, cut the geometry into 20m segments, and transform back into geographic coordinates:

SELECT
  gid, 
  ST_Transform(pg_temp.DivideLine(ST_Transform(geom, _ST_BestSRID(geom)), 20), 4269) AS geom 
FROM hydro;

If the geometry were already in a planar system, this would be much simpler:

SELECT
  gid, 
  pg_temp.DivideLine(geom, 20) AS geom 
FROM hydro;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment