PostGIS: ST_Buffer de lado único da cadeia de linha produz uma saída estranha
No exemplo abaixo, tenho uma tabela PostGIS de cadeia de linha (em preto e amarelo) e um polígono de saída ST_Buffer de lado único (em vermelho). A distância do buffer é baseada em um valor de atributo armazenado na tabela de cadeia de linha.
Como você pode ver, um dos buffers está incorreto e corta uma seção de si mesmo para uma certa quantidade dele. Por que isso aconteceu? Isso pode ser consertado? Parece ser um problema em que a seção da cadeia de linha se torna côncava.

Experimente você mesmo usando uma consulta semelhante:
SELECT ST_BUFFER('LineString (638327 331059, 638337 331048, 638337 331037, 638343 331023, 638358 331014, 638380 330991, 638382 330978, 638391 330966, 638410 330959, 638420 330953)',50,'side=right')
Em outro exemplo, estou vendo isso acontecer (a linha preta é 1 recurso, assim como o polígono do buffer):

E tente este com este:
SELECT ST_BUFFER('LineString (600296 172961, 600304 172962, 600307 172965, 600307 172969, 600307 172971, 600309 172974, 600308 172976, 600307 172979, 600306 172981, 600307 172982, 600311 172980, 600313 172979, 600317 172979, 600321 172982, 600325 172982, 600327 172979, 600328 172976, 600331 172974, 600338 172974)',10,'side=right')
Aumente as distâncias do buffer para resultados mais estranhos. EPSG: 27700 em ambos os casos.
Respostas
Eles são causados por deficiências no algoritmo de buffer unilateral (não são bugs, são limitações conhecidas do projeto do algoritmo).
Isso é registrado como um problema GEOS . No entanto, ainda não há ETA para uma correção.
Eu criei um pipeline de solução alternativa que corrige esse problema. Envolve a criação de algumas tabelas intermediárias temporárias ao longo do caminho, mas você pode excluí-las rapidamente.
- Buffer sua linha usando
ST_BUFFER
normalmente, você não terá uma saída caótica. (ou seja, não use o'side=left/right'
parâmetro). - Use
ST_Split
para dividir o buffer da etapa 1 pela metade ao longo do centro usando a linha.ST_UNION
a linha com linhas de conexão adjacentes! isso irá garantir que a linha de corte se estenda através e além do buffer. Não vai cortar nada de outra forma. - Proteja sua linha novamente, mas desta vez apenas um lado. Esse deve ser o lado que você não quer.
- Crie uma tabela de pontos usando
ST_PointOnSurface
para cada forma de buffer do lado 'errado'. - Use esta nova tabela de pontos para excluir quaisquer polígonos do buffer de polígono dividido (da etapa 2) encontrados cruzando os pontos.
- Agora você fica com o formato do buffer cheio com o lado 'errado' removido dele. ie. você fica com o lado correto desejado.
Eu resumi isso muito e assumi que para cada segmento de linha você tem uma linha de conexão adjacente para ajudar no corte. Eu também fiz isso para um litoral com 1000 segmentos. Portanto, usei uma tabela de host para inserir cada iteração das etapas acima. Para percorrer cada segmento de linha, assegurei-me de que a tabela de linha tivesse uma coluna de id de auto-incremento (assim, para cada segmento de linha, eu poderia mesclá-lo com o segmento anterior e posterior: ou seja, n-1, n, n + 1). Atualizarei esta resposta em breve para esclarecer mais.