Я боровся з проблемою пару днів і зрозумів, що багато людей також застрягають, коли тема перехрестя в 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)?