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