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?
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
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
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
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).
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.