Así que hay muchas soluciones a tu pregunta y esta es una de ellas :-).
Tu caso es particular y problemático, porque para un objeto lineal dividido en segmentos en los puntos de inflexión, es difícil escribir un algoritmo que resuelva situaciones complejas de comportamiento de los objetos de amortiguación, además, se complican por los valores de longitud y anchura de la amortiguación. Como resultado, para su caso con sus condiciones y geodatos, sugiero posibles soluciones a su pregunta. Crea previamente las funciones personalizadas ST_SnapPolygonToLine() y ST_PointsInStarPolygon(), las encontrarás aquí en GIS Stack Exchange... Ejecute el script SQL:
WITH
tbla AS (SELECT row_number() over() AS id, ST_LineSubstring( d.geom, substart, CASE WHEN subend > 1 THEN 1 ELSE subend END) geom
FROM (SELECT row_number() over() AS id, geom, ST_Length(geom) len, 8 sublen FROM line) AS d CROSS JOIN LATERAL (
SELECT i, (sublen * i)/len AS substart, (sublen * (i+1))/len AS subend
FROM generate_series(0, floor(d.len/sublen)::integer) AS t(i) WHERE (sublen * i)/len <> 1.0) AS d2),
tblb AS (SELECT row_number() over() AS id, ST_Buffer(geom, 4,'join=mitre mitre_limit=5.0') as geom FROM tbla),
tblc AS (SELECT row_number() over() AS id, ST_OffsetCurve(geom, 4) geom FROM tbla),
tbld AS (SELECT row_number() over() AS id, ST_SnapPolygonToLine(a.geom, b.geom) geom FROM tbla a JOIN tblc b ON true AND a.id=b.id),
tble AS (SELECT row_number() over() AS id, ST_OffsetCurve(geom, -4) geom FROM tbla),
tblf AS (SELECT row_number() over() AS id, ST_SnapPolygonToLine(a.geom, b.geom) geom FROM tbla a JOIN tble b ON true AND a.id=b.id),
tblg AS (SELECT row_number() over() AS id, ST_Union(a.geom, b.geom) geom FROM tbld a JOIN tblf b ON true AND a.id=b.id)
SELECT a.id, ST_Intersection(a.geom, b.geom) as geom FROM tblb a, tblg b WHERE ST_Intersects (a.geom, b.geom) AND a.id=b.id ORDER BY a.id
El resultado se muestra en la figura 1.
Figura 1.
Si está satisfecho con los contornos suaves de los bordes del buffer, ejecute el siguiente script SQL:
WITH
tbla AS (SELECT row_number() over() AS id, ST_LineSubstring( d.geom, substart, CASE WHEN subend > 1 THEN 1 ELSE subend END) geom
FROM (SELECT row_number() over() AS id, geom, ST_Length(geom) len, 8 sublen FROM line) AS d CROSS JOIN LATERAL (
SELECT i, (sublen * i)/len AS substart, (sublen * (i+1))/len AS subend
FROM generate_series(0, floor(d.len/sublen)::integer) AS t(i) WHERE (sublen * i)/len <> 1.0) AS d2),
tblb AS (SELECT row_number() over() AS id, ST_OffsetCurve(geom, 4) geom FROM tbla),
tblc AS (SELECT row_number() over() AS id, ST_OffsetCurve(geom, -4) geom FROM tbla)
(SELECT row_number() over() AS id, ST_SnapPolygonToLine(a.geom, b.geom) geom FROM tblb a JOIN tblc b ON true AND a.id=b.id)
El resultado se muestra en la imagen 2.
Figura 2.
Soluciones espaciales originales...
Traducido con www.DeepL.com/Translator (versión gratuita)