Упростить shape-файл для мелких масштабов. Одно решение есть.

Добрый день.

Через osmfilter и ogr2ogr выдёргиваю нужные мне слои и сохраняю их в шейпфайлы. Нужно упростить геометрию для мелких масштабов. У ogr2ogr есть параметр -simplify, но работает он вот так:

Остается куча меких ненужных полигончиков. Я сделал фильтрацию по площади (переменная OGR_GEOM_AREA в sql-запросе), но мелкие внутренние inner-области полигонов остались, их видно на картинке. И из-за них упрощение не может быть выполнено, так сказать “в полной мере”. На картинке гребешок сверху должен был быть срезан, но паразитные внутренние области не дали алгоритму этого сделать.

Возникла мысль применить для геометрии операцию “buffer” с положительным, а потом еще раз с отрицательным оффсетом. Буфер просто съест всю мелочь, правда, еще и склеит близлежащие линии. Но в целом результат неплохой, проверял в QGIS. Для автоматизации надо будет написать скрипт, а входные данные еще и предварительно порезать на фрагметы.

Прежде чем начать с этим всем возиться, хотел бы узнать, может, есть более простые решения? Или, может, вообще где-то лежат готовые упрощенные данные? Слепленный из coastline и упрощенный океан я взял с openstreetmapdata.com, а русла рек там никуда не годятся, все в треугольничках. Natural Earth не предлагать, для 6-го масштаба уже не годится, к тому же мне нужны еще и леса и пустыни.

В общем, буферизацией и решил задачу. У меня на одном из этапов используется самописная приблуда на основе libGEOS, вписал туда между строк пару вызовов GEOSBuffer() и готово:

Это в значительно большем масштабе. На скриншоте из первого поста была приближена правая верхняя часть петли. В новой версии, как видите, уже никакого мусора.

Если кому есть что добавить, пишите, почитаем.

Попробуй посчитать скелет https://en.wikipedia.org/wiki/Topological_skeleton, я даже как-то давно находил крутую либу на крестах для этого. И потом, уже имея скелет, можно достаточно сильно варьировать изменения в ту или иную сторону. Как вариант, можно попробовать растеризовать, пофильтровать кучей фильтров вроде разных матриц свертки, трассировать обратно, можно через промежуточные данные вроде скелетика, и хоть это сожрет кучу памяти/времени, качество результата должно быть на высоте, так как на каждом этапе можно контролировать промежуточные результаты.

А вот это:
https://doc.cgal.org/latest/Polyline_simplification_2/index.html#Chapter_2D_Polyline_simplification
это не то, что вам нужно?
Или сразу вот это: https://postgis.net/docs/ST_SimplifyVW.html

Скелет бесполезен, он не дает ширину. К тому же из первой картинки получится офигенно сложный скелет, содержащий всё то, от чего, наоборот, надо избавиться.

Прогонять через PostGIS это как-то не очень рационально. А вот CGAL прикрутить, наверное, можно. Програма на Си, работаю с libGEOS (честно говоря, я думал, что GEOS и CGAL это одно и то же, одно использует другое). Основная возня будет преобразованием GEOSGeom_t в CGAL::Polygon_2 и обратно.