Создайте мозаику наподобие диаграммы Вороного из непересекающихся многоугольников

12

На рисунке ниже показана проблема :

введите описание изображения здесь

как в (а) у меня есть набор непересекающихся многоугольников, как геометрии в PostGIS. Мне нужно что-то вроде (б) , «мозаика» этого набора полигонов, построение его по критерию «область влияния» ... Это похоже на конструкцию Вороного (показано (с) ): на самом деле, если бы полигоны были точки, регионы влияния Вороного.

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

PS: мне нужно, как и у Вороного, разграничение пространства (квадратный кадр в (b) ) игнорируется.


Эта проблема похожа на эту другую о линиях .

РЕДАКТИРОВАТЬ (после комментария @FelixIP)

Я предпочитаю оставаться в векторной вселенной, чтобы не потерять точность (например, используя ST_DelaunayTriangles и добавляя и вычитая внутренности из исходных многоугольников, они адаптируют решение с двойным графом ) ... Некоторые простые и автоматические пакеты, такие как pprepair (помогают как топологические инструменты QGIS не являются автоматическими). Но растр , возможно, проще и требует меньше ресурсов процессора.

Эта иллюстрация «процесса GRID» также является допустимым решением, если предположить, что она может обеспечить такую ​​же точность и «евклидову область влияния».

введите описание изображения здесь

В ARCGIS существует инструмент пространственного анализа, известный как Euclidean Allocation , поэтому, возможно, существует аналогичное решение PostGIS , начиная с набора полигонов (классификация, растеризация и возврат полигонов).

Питер Краусс
источник
Спасибо @Nir, извините за путаницу с точками, я не использую точки, только полигоны в качестве пунктов (a) и (b) иллюстрации ... У вас есть ссылка вашей подсказки о решении?
Питер Краусс
В arcgis есть растровое решение, называемое евклидовым распределением или близостью
FelixIP
Спасибо @FelixIP, я отредактировал для "ну давай растровые решения" ;-)
Питер Краусс
Если вы удалите свои полигоны из их размера. Вы можете оставить полигон. Скелет этого gis.stackexchange.com/questions/177/… это то, что вам нужно, я думаю. Реализация - важная вещь, хотя
FelixIP
1
@ Кирилл, я могу просмотреть твои сценарии ... На следующей неделе. Размещение чего-то, что кажется решением с современными функциями PostGIS, будет хорошим первым шагом.
Питер Краусс

Ответы:

1

Итак, я приготовлю торт для вас - блюдо с фруктами, используя инструменты 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 введите описание изображения здесь

Все с этого дня, теперь каждый научится печь вкусные пироги - блюдо с фруктами. Помоги себе всем и выбери куски, которые тебе нравятся, хватит всем.

(Жаль, что я действительно не могу накормить всех людей, не электронными пирожными, а настоящими пирогами, возможно, голод закончится на Земле ...)

Изменить: вишня на пироге может выглядеть так :-):

WITH
tbla AS (SELECT (ST_DumpPoints(geom)).geom geom FROM poly),
tblb AS (SELECT ((ST_Dump(ST_VoronoiPolygons(ST_Collect(geom)))).geom) geom FROM tbla),
tblc AS (SELECT ST_Intersection(a.geom, b.geom) geom FROM tblb a JOIN poly_extent b ON ST_Intersects(a.geom,b.geom)),
tbld AS (SELECT id, ((ST_Dump(geom)).geom) geom FROM poly GROUP BY id, geom)
SELECT id, ST_Union(a.geom) as geom FROM tblc a JOIN tbld b ON ST_Intersects(a.geom, b.geom) GROUP BY id;

или

WITH
tbla AS (SELECT (ST_DumpPoints(geom)).geom geom FROM polygons),
tblb AS (SELECT ((ST_Dump(ST_VoronoiPolygons(ST_Collect(geom)))).geom) geom FROM tbla),
tblc AS (SELECT id, ((ST_Dump(geom)).geom) geom FROM polygons GROUP BY id, geom)
SELECT id, ST_Union(a.geom) geom FROM tblb a JOIN tblc b ON ST_Intersects(a.geom, b.geom) GROUP BY id;

С тобой был добрый и справедливый мистер Бейкер, всем спасибо и удачи: -) ...

Оригинальные решения.

Этот скрипт называется: ST_VoronoiDiagramsFromPolygons.

Кирилл Михальченко
источник
1
Привет, хорошие иллюстрации и, кажется, хороший результат (!). Предложение для краткого обсуждения, см. Решение @geogeek, шаги в QGis кажутся основными шагами PostGIS здесь ... Зачем это нужно ST_Bufferи ST_ConvexHull? Есть альтернативный алгоритм?
Питер Краусс
1) Смотрите, ST_Buffer и полигоны создаются для того, чтобы уменьшить разделительные линии между исходными фигурами во время применения функции Вороного, поэтому, чем больше размер буфера, который вы можете указать, тем более плавно будут построены разделительные линии как функция Вороного ... 2) ST_ConvexHull из множества цифр на каждом многоугольнике, нужном нам многоугольнике ... 3) Сегодня я вижу свое решение твоего вопроса, я не знаю, что случится со всеми нами и наши решения в будущем ...
Кирилл Михальченко
Еще одно важное значение буферных линий заключается в том, что они помогут нам выбрать фрагменты из результата функции Вороного для создания комбинированных полигонов для каждой фигуры ...
Кирилл Михальченко,
Кстати, я приветствую улучшение кода и подхода, чтобы они не ухудшали результат ...
Кирилл Михальченко
1
Привет, Кирилл, я согласен, что ST_Buffer - это хороший вариант для нормализации контурных линий, идеальный (!). О ST_ConvexHull, это всего лишь любопытство, какие результаты мы можем получить после рисунка 6 poly_voronoi_unionбез ST_ConvexHull.
Питер Краусс
8

У Postgis нет выделенной функции для voronoi, но Qgis содержит функцию vornoi, которая может создавать полигоны voronoi из точек, поэтому, используя qgis, я выполнил следующие шаги, чтобы получить такой результат:

-сделать точки из полигонов с помощью extract nodesфункций.

-сделать вороньи многоугольники, используя вори-функции в Qgis.

создать пространственное соединение в Qgis.

-растворять результаты.

введите описание изображения здесь

geogeek
источник
1
Хорошее решение (!) И спасибо за иллюстрацию. Вы можете улучшить это? Посмотрите на левый прямоугольник ниже, это было 4 точки в Вороном, и центр прямоугольника не имеет представления, искажая его область (потеря в треугольнике) ... Возможно, улучшение возможно при регулярной выборке каждого полигона ... и возможно также некоторые внутренние пункты.
Питер Краусс
Я использую инструмент уплотнения в ArcGIS. Это значительно улучшает близость полигонов. +1
FelixIP
3

Хорошо - подумал об этом немного и обнаружил, что это было похоже на то, на что я смотрел в последнее время.

Возьми свои стартовые полисы:

введите описание изображения здесь

Создайте новый атрибут с числом (в моем случае 100). Используйте инструмент Вектор-> Инструменты исследования -> Случайные точки внутри многоугольников, который сгенерирует (100) точек внутри каждого многоугольника: введите описание изображения здесь

Затем Vector-> Geometry tools -> Voronoi для генерации полисов на основе этого точечного слоя.

введите описание изображения здесь

Теперь вы можете использовать инструмент Вектор -> Пространственный запрос: выберите точки, принадлежащие одному полигону (или одному из полигонов). Используйте инструмент пространственного запроса, чтобы сгенерировать выбор ваших полигонов вороной, которые применяются к этому полигону. Добавьте атрибут к многоугольнику Ворони, который соответствует интересующему многоугольнику. (Я просто использовал 1,2,3,4)

Теперь вы можете Vector-> Инструменты геообработки-> распустить на основе вашего нового атрибута.

введите описание изображения здесь

А.А.
источник
Спасибо @AAmes (!), Иллюстрации хороши, и метод является хорошей альтернативой ... Но вопрос о «алгоритме SQL (или некотором специфичном для PostGIS)», а теперь щедрость за использование функции ST_VoronoiPolygons () , которая, возможно, решит все проблемы в один клик ;-)
Питер Краусс
@AAmes Быстрый поиск показывает, что этот метод действительно можно использовать и в PostGIS. Как создавать случайные точки в многоугольнике в postgis, объясняет создание точек из многоугольников, и оттуда это должно быть довольно просто.
Фил Г
Моя награда была для вас, как стимул (добро пожаловать сюда!), Но ЭТО ОТВЕТ РАБОТАЕТ для вопроса и требований к награде.
Питер Краусс
Спасибо, Питер, я видел твои записи, но, к сожалению, у меня не было возможности вернуться и заняться этим. У меня пока нет опыта работы с PostGIS, и мне потребовалось бы больше времени, чем у меня, чтобы дать хороший ответ. Я надеюсь, что наше исследование этого пространства будет полезным для людей в будущем, возможно, если я скоро получу треск в PostGIS, я вернусь и еще раз попробую его на практике!
AA
2

Случайные точки - хорошая идея для генерации вороного многоугольника из многоугольников, это работает довольно хорошо, но это довольно плохо для многоугольников близко друг к другу: введите описание изображения здесь введите описание изображения здесь

ST_ApproximateMedialAxis - еще одна хорошая альтернатива, если использовать PostGIS: расчет диаграмм Вороного для полигонов.

Лео
источник