На рисунке ниже показана проблема :
как в (а) у меня есть набор непересекающихся многоугольников, как геометрии в PostGIS. Мне нужно что-то вроде (б) , «мозаика» этого набора полигонов, построение его по критерию «область влияния» ... Это похоже на конструкцию Вороного (показано (с) ): на самом деле, если бы полигоны были точки, регионы влияния Вороного.
Резюмируя: мне нужен алгоритм SQL (или какой-то специфичный для PostGIS), который генерирует «мозаику» из набора непересекающихся многоугольников. (возможно, цикл маленьких операций ST_Buffer и ST_Difference)
PS: мне нужно, как и у Вороного, разграничение пространства (квадратный кадр в (b) ) игнорируется.
Эта проблема похожа на эту другую о линиях .
РЕДАКТИРОВАТЬ (после комментария @FelixIP)
Я предпочитаю оставаться в векторной вселенной, чтобы не потерять точность (например, используя ST_DelaunayTriangles и добавляя и вычитая внутренности из исходных многоугольников, они адаптируют решение с двойным графом ) ... Некоторые простые и автоматические пакеты, такие как pprepair (помогают как топологические инструменты QGIS не являются автоматическими). Но растр , возможно, проще и требует меньше ресурсов процессора.
Эта иллюстрация «процесса GRID» также является допустимым решением, если предположить, что она может обеспечить такую же точность и «евклидову область влияния».
В ARCGIS существует инструмент пространственного анализа, известный как Euclidean Allocation , поэтому, возможно, существует аналогичное решение PostGIS , начиная с набора полигонов (классификация, растеризация и возврат полигонов).
источник
Ответы:
Итак, я приготовлю торт для вас - блюдо с фруктами, используя инструменты PostGis, как вы и просили, если я правильно понял вопрос, и, как я уже говорил, ответственность за работу печи PostGIS несет ее творческая команда.
Я попрошу не обижаться ни на кого в моем стиле юмора и понимать это как игру!
Исходный файл представляет собой нарезанные фрукты и простые формы (в дальнейшем именуемые фруктами), см. Рисунок 1 ниже.
Вот мой рецепт, и в этом мне помогут дорогие программисты, о которых вы узнаете позже. Давайте начнем, и для этого мы создадим тесто, в которое будут заложены наши фрукты, для чего запустим скрипт:
create table poly_extent as SELECT ST_SetSRID(ST_Buffer(ST_Envelope(ST_Extent(geom)),0.05),4326) as geom FROM poly;
Смотрите результат на рисунке 2 ниже
Теперь, если фруктов мало, как на моей картинке, создайте границу внешнего буфера на фрукте или если есть много фруктов, создайте границу отрицательного буфера, для чего запустите скрипт:
create table poly_buff_dump as SELECT ((ST_Dump(ST_Boundary(ST_Union(ST_Buffer((geom),0.01, 'join=mitre mitre_limit=5.0'))))).geom) geom FROM poly;
И нарезать буферные линии вокруг каждого фрукта
UPDATE poly_buff_dump SET geom=ST_RemovePoint(geom, ST_NPoints(geom)-1) WHERE ST_IsClosed(geom)=true;
Смотрите результат на рисунке 3 ниже(На самом деле, я думал, что в результате получу ломаные линии (например, по кругу), но если фигуры сложные, иногда получаются разрывы, неправильные, например, одна сторона прямоугольника отвалилась и т. Д. )
Затем вам нужно удобно разделить полученные линии на равные отрезки и извлечь из них точки
create table poly_buff_dump_pt as SELECT (ST_DumpPoints((geom))).geom geom FROM poly_buff_segm;
Результат, см. Рисунок 4 ниже
Теперь запустите инструмент Вороного, в этом месте я использовал инструмент, предложенный по ссылке MickyT: /gis//a/172246/120129 , в результате чего вы создадите таблицы с именем «voronoi». За то, что «мой первый помощник» отделен от шеф-повара благодаря шеф-повару! :-).
Второй способ на этом шаге - запустить функцию ST_VoronoiPolygons.
Результат, см. Рисунок 5 ниже
Теперь отрежьте лишние части, запустив скрипт:
create table poly_voronoi_cut as SELECT ST_Intersection(a.geom, b.geom) geom FROM voronoi a INNER JOIN poly_extent b ON ST_Intersects(a.geom, b.geom);
Результат, см. Рисунок 6 ниже.Теперь запустите скрипт, чтобы выровнять тип геоданных в LineString:
create table poly_voronoi_dump as SELECT (ST_Dump(geom)).geom as geom FROM poly_voronoi_cut;
А теперь я попрошу «моего второго помощника» взять на себя мои обязанности и хорошо перемешать торт (Джефф - /gis//a/785/120129 ), выровняв его в один слой, и для этого Спасибо за это!CREATE TABLE poly_overlay_cut AS SELECT geom FROM ST_Dump(( SELECT ST_Polygonize(geom) AS geom FROM ( SELECT ST_Union(geom) AS geom FROM ( SELECT ST_ExteriorRing(geom) AS geom FROM poly_voronoi_dump) AS lines ) AS noded_lines ) );
Теперь мне пора приступать к работе, для чего я запускаю скрипт:create table poly_voronoi_union as SELECT b.id, (ST_ConvexHull(ST_Union(a.geom, b.geom))) geom FROM poly_overlay_cut a INNER JOIN poly_buff_dump b ON ST_Intersects(a.geom, b.geom) GROUP BY b.id, a.geom, b.geom;
и другой скрипт:create table poly_voronoi_union_area as SELECT ST_Union(ST_ConvexHull(ST_BuildArea(geom))) as geom FROM poly_voronoi_union GROUP BY id;
см. рисунок 7 нижеКак вы можете видеть на рисунке, наши разрезы имеют небольшие слои, которые можно удалить, как вариант с помощью ST_SnapToGrid (или другим способом):
И наконец, мы будем вырезать наши пироги из нашего пирога, я даже немного устал, стоя у духовки :-)
create table polygon_voronoi_result as SELECT (ST_Dump(ST_Difference(a.geom, b.geom))).geom as geom FROM poly_voronoi_union_area_snap as a JOIN poly b ON ST_Intersects(a.geom, b.geom);
Результат см. Рисунок 8Все с этого дня, теперь каждый научится печь вкусные пироги - блюдо с фруктами. Помоги себе всем и выбери куски, которые тебе нравятся, хватит всем.
(Жаль, что я действительно не могу накормить всех людей, не электронными пирожными, а настоящими пирогами, возможно, голод закончится на Земле ...)
Изменить: вишня на пироге может выглядеть так :-):
или
С тобой был добрый и справедливый мистер Бейкер, всем спасибо и удачи: -) ...
Оригинальные решения.
Этот скрипт называется: ST_VoronoiDiagramsFromPolygons.
источник
ST_Buffer
иST_ConvexHull
? Есть альтернативный алгоритм?ST_ConvexHull
, это всего лишь любопытство, какие результаты мы можем получить после рисунка 6poly_voronoi_union
без ST_ConvexHull.У Postgis нет выделенной функции для voronoi, но Qgis содержит функцию vornoi, которая может создавать полигоны voronoi из точек, поэтому, используя qgis, я выполнил следующие шаги, чтобы получить такой результат:
-сделать точки из полигонов с помощью
extract nodes
функций.-сделать вороньи многоугольники, используя вори-функции в Qgis.
создать пространственное соединение в Qgis.
-растворять результаты.
источник
Хорошо - подумал об этом немного и обнаружил, что это было похоже на то, на что я смотрел в последнее время.
Возьми свои стартовые полисы:
Создайте новый атрибут с числом (в моем случае 100). Используйте инструмент Вектор-> Инструменты исследования -> Случайные точки внутри многоугольников, который сгенерирует (100) точек внутри каждого многоугольника:
Затем Vector-> Geometry tools -> Voronoi для генерации полисов на основе этого точечного слоя.
Теперь вы можете использовать инструмент Вектор -> Пространственный запрос: выберите точки, принадлежащие одному полигону (или одному из полигонов). Используйте инструмент пространственного запроса, чтобы сгенерировать выбор ваших полигонов вороной, которые применяются к этому полигону. Добавьте атрибут к многоугольнику Ворони, который соответствует интересующему многоугольнику. (Я просто использовал 1,2,3,4)
Теперь вы можете Vector-> Инструменты геообработки-> распустить на основе вашего нового атрибута.
источник
Случайные точки - хорошая идея для генерации вороного многоугольника из многоугольников, это работает довольно хорошо, но это довольно плохо для многоугольников близко друг к другу:
ST_ApproximateMedialAxis - еще одна хорошая альтернатива, если использовать PostGIS: расчет диаграмм Вороного для полигонов.
источник