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