Створіть мозаїку на зразок діаграми Вороного з розрізнених багатокутників


12

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

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

як у (а) у мене є набір розрізнених багатокутників, як геометрії в PostGIS. Мені потрібно щось на зразок (б) , "мозаїки" цього набору багатокутників, будуючи його за критеріями "регіону впливу" ... Це як конструкція Вороного (проілюстрована в (с) ): насправді, якби полігони були бали, регіони впливу - Вороний.

Підсумовуючи: мені потрібен алгоритм SQL (або якийсь специфічний для PostGIS), який генерує "мозаїку" набору роз'єднаних багатокутників. (можливо, цикл з невеликих операцій ST_Buffer та ST_Difference)

PS: Мені потрібно, як і Вороному, щоб розмежування простору (рамка квадрата в (b) ) ігнорувалося.


Ця проблема схожа на цю іншу щодо рядків .

EDIT (після коментаря @FelixIP)

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

Ця ілюстрація "GRID-процесу" також є дійсною як рішення, припускаючи, що вона може дозволити однакову точність та "зростає область евклідового впливу".

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

В ARCGIS існує інструмент просторового аналізу, відомий як Евклідовий розподіл , тому, можливо, існує подібне рішення PostGIS , починаючи з набору багатокутників (класифікація, растеризація та повернення багатокутників).


Дякуємо @Nir, вибачте, що плутайте точки, я не використовую точки, лише багатокутники як пункти (а) та (б) ілюстрації ... Чи є у вас посилання вашої підказки щодо рішення?
Пітер Краусс

У аркгізі є растровий розчин, який називається еуклеодовим виділенням або близькістю
FelixIP

Дякуємо @FelixIP, я відредагував "добре приходять растрові рішення" ;-)
Пітер Краус

Якщо ви видалите багатокутники з їх розміру.aspolygon, вам залишиться багатокутник. Скелет його gis.stackexchange.com/questions/177/… - це те, що вам потрібно, я думаю. Реалізація є великим, хоча
FelixIP

1
@Cyril, я можу переглянути ваші сценарії ... Наступного тижня. Опублікувати щось, що здається рішенням із сучасними функціями PostGIS, буде хорошим першим кроком.
Пітер Краус

Відповіді:


2

Отже, я приготую торт - фруктову тарілку, використовуючи інструменти 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 нижче

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

Тепер запустіть інструмент Voronoi, в цьому місці я використав інструмент, запропонований посиланням 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;

Переглянути сценарій 01.04.2020:

WITH tbla AS (
WITH atbl AS (SELECT id, (ST_ExteriorRing(((ST_Dump(geom)).geom))) geom FROM polygons),
intervals AS (SELECT generate_series (0, 501) as steps)
SELECT steps AS stp, ST_LineInterpolatePoint(geom, steps/(SELECT count(steps)::float-1 FROM intervals)) geom FROM atbl, intervals GROUP BY id, intervals.steps, geom),
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функцій.

-виготовити ворної багатокутники, використовуючи функції Voroi в Qgis.

-зробити просторове з'єднання в Qgis.

-розподіл результатів.

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


1
Гарне рішення (!), І дякую ілюстрації. Чи можете ви її покращити? Подивіться лівий прямокутник внизу, він був у Вороного на 4 бали, а центр прямокутника не має представлення, спотворюючи його область (втрачається до трикутника) ... Можливо, покращити можна, роблячи регулярний відбір проб кожного многокутника ... і можливо, також деякі інтер’єрні моменти.
Пітер Краус

Я використовую інструмент ущільнення в ArcGIS. Це значно покращує полігони близькості. +1
FelixIP

3

Добре - трохи подумав над цим і виявив, що це щось на зразок, на який я дивлюся останнім часом.

Візьміть свій стартовий поліс:

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

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

Потім Вектор-> Інструменти геометрії -> Вороной для створення полісів на основі цього точкового шару.

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

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

Тепер ви можете вектор-> Інструменти для геообробки-> розчинити на основі нового атрибута.

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


Спасибі @AAmes (!), Ілюстрації хороші, а метод - хороша альтернатива ... Але питання в тому, що "алгоритм SQL (або якийсь специфічний для PostGIS)", а тепер - щедрість щодо використання функції ST_VoronoiPolygons () , який, можливо, вирішить усю проблему одним клацанням ;-)
Пітер Краус

@AAmes Швидкий пошук показує, що цей метод справді може бути використаний і в PostGIS. Як створити випадкові точки в полігоні в постгітах, пояснюється створення точки з полігонів, і звідти це повинно бути досить прямо.
Філ Г

Моя щедрість була для вас як стимул (ласкаво просимо сюди!), Але ЦЕ ВІДПОВІДЬ ВІДПОВІДУЄМО за запитання та вимоги щедрості.
Пітер Краус

Дякую Петру, я побачив ваші записки, але, на жаль, у мене не було можливості повернутися і виступити з ним. Я ще не маю досвіду в PostGIS, і це знадобило б мені більше часу, ніж я мала, щоб дати будь-яку хорошу відповідь. Я сподіваюся, що наше дослідження цього космосу буде корисним людям у майбутньому, можливо, якщо я скоро отримаю тріщину на PostGIS, я повернусь і зроблю ще одне ударення на практиці!
АА

2

Випадкові точки - це гарна ідея для формування багатокутника Вороного з багатокутників, він працює досить добре, але це дуже погано для полігонів, близьких один до одного: введіть тут опис зображення введіть тут опис зображення

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.