I want to buffer rivers/streams for a topographic map. I'm using a PostgreSQL/PostGIS database. Usually, I create buffer with ST_Buffer with a constant width.
For example, the width of a river buffer should be increasing from the spring to the estuary with a distinct value.
Is there a way to create buffer with an increasing or decreasing width starting from a distinct point and ending at a distinct point?
UPDATE
With the help of simplexico I tried to create some geometries that could help to create a thinning buffer around a linestring:
First I create the buffer lines parallel to the river geom and insert them into a table called offsetcurve
:
WITH geometries AS (
SELECT
gid,
(ST_Dump(geom)).geom AS geom
FROM waterways
WHERE name='river_name')
SELECT
gid,
ST_OffsetCurve(geom, 10, 'quad_segs=4 join=mitre') AS pos_curve,
ST_Reverse(ST_OffsetCurve(geom,-10, 'quad_segs=4 join=mitre')) AS neg_curve
FROM geometries;
I have to use the reverse function for a further step.
The next step is to dump the points from the buffer lines and the river geom and insert them into a table called offsetpoints
:
SELECT
offsetcurve.gid,
(ST_DumpPoints(offsetcurve.pos_curve)).geom AS pos_curve_dump,
(ST_DumpPoints(offsetcurve.neg_curve)).geom AS neg_curve_dump,
ST_SetSRID((ST_DumpPoints(geometries.geom)).geom, 31468) AS river_dump
FROM offsetcurve, geometries
After that I create lines between the buffer line points and the river geom points and store them in a table called offsetazimuth
:
SELECT
offsetpoints.gid,
ST_Azimuth(offsetpoints.pos_curve_dump, river_dump) AS pos_curve_azimuth,
ST_MakeLine(offsetpoints.pos_curve_dump, river_dump) AS pos_azimuth_line,
ST_Azimuth(offsetpoints.neg_curve_dump, river_dump) AS neg_curve_azimuth,
ST_MakeLine(offsetpoints.neg_curve_dump, river_dump) AS neg_azimuth_line
FROM offsetpoints
Visualizing all new geometries, I have the following picture:
The red and blue points are dumps from the buffer line. The green points are the river geom dumps.
The blue and red points are connected to the green points with the offsetazimuth line.
I can change the position of the buffer points (e.g. for one buffer line) along the azimuth line with:
SELECT
ST_MakePoint(
ST_X(st_endpoint(pos_azimuth_line)) - (ST_X(st_endpoint(pos_azimuth_line))-st_x(st_startpoint(pos_azimuth_line)))/6,
st_y(st_endpoint(pos_azimuth_line)) - (st_y(st_endpoint(pos_azimuth_line))-st_y(st_startpoint(pos_azimuth_line)))/6
) as geom
FROM offsetazimuth
The results are new points with a constant distance from the river geom:
The first step of a final solution has to be that the first point has the distance like (buffer_width(B)-buffer_width(A))/count(river_dump_points)
(see first picture) from the river geom on the offsetazimuth line (see the last but one query).
For example:
The first new point has a distance of (200m-100m)/100=1m
from the river geom, the second one ((200m-100m)/100)*2=2m
and so on. 200m
is the maximum width,100m
is the minimum width of the wanted buffer. 100
is the number of dumped points from the river geom.
It's the question if this (increasing or decreasing distance value for every buffer line point) is possible with PostGIS!?
The next idea could be a function: setting parameters like the gradient or the length where the buffer has to take place.