Я боролся с проблемой в течение нескольких дней и понял, что многие люди также застревают, когда речь идет о пересечениях в PostGIS (v2.5). Вот почему я решил задать более подробный и общий вопрос.
У меня есть следующая таблица:
DROP TABLE IF EXISTS tbl_foo;
CREATE TABLE tbl_foo (
id bigint NOT NULL,
geom public.geometry(MultiPolygon, 4326),
att_category character varying(15),
att_value integer
);
INSERT INTO tbl_foo (id, geom, att_category, att_value) VALUES
(1, ST_SetSRID('MULTIPOLYGON (((0 6, 0 12, 8 9, 0 6)))'::geometry,4326) , 'cat1', 2 );
INSERT INTO tbl_foo (id, geom, att_category, att_value) VALUES
(2, ST_SetSRID('MULTIPOLYGON (((5 0, 5 12, 9 12, 9 0, 5 0)))'::geometry,4326), 'cat1', 1 );
INSERT INTO tbl_foo (id, geom, att_category, att_value) VALUES
(3, ST_SetSRID('MULTIPOLYGON (((4 4, 3 8, 4 12, 7 14,10 12, 11 8, 10 4, 4 4)))'::geometry,4326) , 'cat2', 5 );
Это выглядит так:
Я хочу получить все дочерние полигоны на основе пересечения родительских полигонов. Для результата можно было бы ожидать:
- Дочерние полигоны без перекрытия между ними.
- Столбец, содержащий сумму значений их родительских полигонов,
- Столбец, содержащий количество родительских полигонов одной категории
- Столбец, содержащий количество другой категории
- Столбец, содержащий категорию дочернего полигона, на основе следующего правила: -Если ВСЕ родительские полигоны принадлежат одному классу, дочерний полигон также имеет этот класс. Иначе, категория дочернего многоугольника является третьей категорией.
Так это будет выглядеть так:
Так, в конце концов, выходная таблица генерируется (для данного примера) будет иметь 7 строк (все 7, неперекрывающиеся, детские многоугольников), содержащие столбцы category
, sum_value
, ct_overlap_cat1
,ct_overlap_cat2
Следующий код, который я начал, дает мне отдельные пересечения, сравнивая одного родителя с другим.
SELECT
(ST_Dump(
ST_SymDifference(a.geom, b.geom)
)).geom
FROM tbl_foo a, tbl_foo b
WHERE a.ID < b.ID AND ST_INTERSECTS(a.geom, b.geom)
UNION ALL
SELECT
ST_Intersection(a.geom, b.geom) as geom
FROM tbl_foo a, tbl_foo b
WHERE a.ID < b.ID AND ST_INTERSECTS(a.geom, b.geom);
Как мне рекурсивно перебрать результат этого упомянутого кода, чтобы, независимо от числа перекрывающихся многоугольников, я всегда получал его «наименьшие» (дочерние) многоугольники (рис. 2)?
Я полагаю, если вы используете тип геометрии полигона вместо MultiPolygon, все станет на свои места:
В результате получается 9 записей, которые соответствуют различным вариантам пересечения в приведенном вами примере.
источник