PostGIS: односторонний ST_Buffer строки строки дает странный вывод

Aug 18 2020

В приведенном ниже примере у меня есть таблица PostGIS со строками (черным и желтым) и односторонний выходной многоугольник ST_Buffer (красный). Расстояние буфера основывается на значении атрибута, хранящемся в таблице строк.

Как вы можете видеть, один из буферов неверен и вырезает часть себя для определенного количества. Почему это произошло? Это можно исправить? Кажется, проблема заключается в том, что участок линии становится вогнутым.

Попробуйте сами, используя аналогичный запрос:

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')

В другом примере я вижу, как это происходит (черная линия - это 1 объект, как и буферный многоугольник):

И попробуйте вот это:

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')

Увеличьте буферные расстояния для посторонних результатов. EPSG: 27700 в обоих случаях.

Ответы

7 dr_jts Aug 18 2020 at 05:53

Это вызвано недостатками в алгоритме одностороннего буфера (не ошибками, это известные ограничения конструкции алгоритма).

Это регистрируется как проблема GEOS . Однако пока нет ETA для исправления.

TheoF Aug 20 2020 at 01:04

Я создал обходной конвейер, который устраняет эту проблему. Это действительно связано с созданием нескольких временных промежуточных таблиц в процессе, но вы можете удалить их на лету.

  1. Используйте ST_BUFFERобычную буферизацию вашей строки , у вас не будет хаотичного вывода. (т.е. не используйте 'side=left/right'параметр).
  2. Используйте, ST_Splitчтобы разделить буфер из шага 1 пополам по центру с помощью линии. ST_UNIONлиния с соседними соединительными линиями! это обеспечит выход линии разреза через буфер и за его пределы . Иначе ничего не порежет.
  3. Снова выполните буферизацию строки, но на этот раз только с одной стороны. Это должна быть та сторона, которую ты не хочешь.
  4. Создайте таблицу точек, используя ST_PointOnSurfaceдля каждой «неправильной» формы буфер.
  5. Используйте эту новую таблицу точек для удаления любых многоугольников из буфера разбитых многоугольников (из шага 2), обнаруженных пересекающими точки.
  6. Теперь у вас остается полная форма буфера с удаленной «неправильной» стороной. т.е. у вас остается желаемая правильная сторона.

Я обобщил все это и предположил, что для каждого сегмента линии у вас есть смежная соединительная линия, которая помогает при резке. Я также сделал это для береговой линии с тысячами сегментов. Итак, я использовал таблицу хостов для вставки каждой итерации описанных выше шагов. Чтобы перебрать каждый линейный сегмент, я убедился, что в линейной таблице есть столбец с автоматически увеличивающимся идентификатором (поэтому для каждого линейного сегмента я мог объединить его с сегментом до и после него: т.е. n-1, n, n + 1). Я скоро обновлю этот ответ, чтобы уточнить больше.