Я хотів би зробити тести на суміжність на шарі посилки (полігони) та об'єднати їх, якщо вони відповідають певним критеріям (може бути розміром). На малюнку нижче я хотів би об'єднати багатокутники 1,2,3 та 4, але не 5.
У мене дві проблеми:
ST_TOUCHES
повертає ІСТИНА, якщо торкаються лише кути, а не відрізок лінії. Я думаю, що мені потрібно ST_RELATE, щоб перевірити, чи є сегменти спільного використання рядків.- В ідеалі я хотів би об'єднати ВСІ суміжні багатокутники в один, але я не впевнений, як масштабувати межі двох - як у, об'єднати 1,2,3 та 4 (і, можливо, більше за фактичними даними) за один раунд.
Структура, яку я маю зараз, заснована на самостійному приєднанні ST_TOUCHES
.
Дані про іграшки
CREATE TABLE testpoly AS
SELECT
1 AS id, ST_PolyFromText('POLYGON ((0 0, 10 0, 10 20, 00 20, 0 0 ))') AS geom UNION SELECT
2 AS id, ST_PolyFromText('POLYGON ((10 0, 20 0, 20 20, 10 20, 10 0 ))') AS geom UNION SELECT
3 AS id, ST_PolyFromText('POLYGON ((10 -20, 20 -20, 20 0, 10 0, 10 -20 ))') AS geom UNION SELECT
4 AS id, ST_PolyFromText('POLYGON ((20 -20, 30 -20, 30 0, 20 0, 20 -20 ))') AS geom UNION SELECT
5 AS id, ST_PolyFromText('POLYGON ((30 0, 40 0, 40 20, 30 20, 30 0 ))') AS geom ;
Вибір
SELECT
gid, adj_gid,
st_AStext(st_union(l2.g1,l2.g2)) AS geo_combo
from (
--level 2
SELECT
t1.id AS gid,
t1.geom AS g1,
t2.id AS adj_gid,
t2.geom AS g2
from
testpoly t1,
testpoly t2
where
ST_Touches( t1.geom, t2.geom )
AND t1.geom && t2.geom
)
l2
Ось вихід:
+-----+---------+-------------------------------------------------------------------------------+
| gid | adj_gid | geo_combo |
+-----+---------+-------------------------------------------------------------------------------+
| 1 | 2 | POLYGON((10 0,0 0,0 20,10 20,20 20,20 0,10 0)) |
+-----+---------+-------------------------------------------------------------------------------+
| 1 | 3 | MULTIPOLYGON(((10 0,0 0,0 20,10 20,10 0)),((10 0,20 0,20 -20,10 -20,10 0))) |
+-----+---------+-------------------------------------------------------------------------------+
| 2 | 1 | POLYGON((10 20,20 20,20 0,10 0,0 0,0 20,10 20)) |
+-----+---------+-------------------------------------------------------------------------------+
| 2 | 3 | POLYGON((10 0,10 20,20 20,20 0,20 -20,10 -20,10 0)) |
+-----+---------+-------------------------------------------------------------------------------+
| 2 | 4 | MULTIPOLYGON(((20 0,10 0,10 20,20 20,20 0)),((20 0,30 0,30 -20,20 -20,20 0))) |
+-----+---------+-------------------------------------------------------------------------------+
| 3 | 1 | MULTIPOLYGON(((10 0,20 0,20 -20,10 -20,10 0)),((10 0,0 0,0 20,10 20,10 0))) |
+-----+---------+-------------------------------------------------------------------------------+
| 3 | 2 | POLYGON((20 0,20 -20,10 -20,10 0,10 20,20 20,20 0)) |
+-----+---------+-------------------------------------------------------------------------------+
| 3 | 4 | POLYGON((20 -20,10 -20,10 0,20 0,30 0,30 -20,20 -20)) |
+-----+---------+-------------------------------------------------------------------------------+
| 4 | 2 | MULTIPOLYGON(((20 0,30 0,30 -20,20 -20,20 0)),((20 0,10 0,10 20,20 20,20 0))) |
+-----+---------+-------------------------------------------------------------------------------+
| 4 | 3 | POLYGON((20 0,30 0,30 -20,20 -20,10 -20,10 0,20 0)) |
+-----+---------+-------------------------------------------------------------------------------+
| 4 | 5 | MULTIPOLYGON(((30 0,30 -20,20 -20,20 0,30 0)),((30 0,30 20,40 20,40 0,30 0))) |
+-----+---------+-------------------------------------------------------------------------------+
| 5 | 4 | MULTIPOLYGON(((30 0,30 20,40 20,40 0,30 0)),((30 0,30 -20,20 -20,20 0,30 0))) |
+-----+---------+-------------------------------------------------------------------------------+
Зауважте, що багатокутник id = 3 ділить точку з id = 1 і, таким чином, повертається як позитивний результат. Якщо я зміню пункт WHERE, ST_Touches( t1.geom, t2.geom ) AND t1.geom && t2.geom AND ST_Relate(t1.geom, t2.geom ,'T*T***T**');
я взагалі не отримаю записів.
Отже, спочатку , як вказати ST_Relate, щоб переконатися, що розглядаються лише посилки, що поділяють сегмент рядка.
І тоді, як би я об'єднав багатокутники 1,2,3,4 в один раунд, згортаючи результати вищезгаданого виклику, увесь час визнаючи, що суміжність 1 до 2 - це те саме, що і зворотне?
Оновлення
Якщо додати це до where
пункту, я, очевидно, отримую лише багатокутники, а не мультиполігони, тим самим відмиваючи помилкові позитиви для моїх цілей - кутові дотики будуть ігноровані.
GeometryType(st_union(t1.geom,t2.geom)) != 'MULTIPOLYGON'
Хоча це не ідеально (я б скоріше використовував перевірки топології з ST_RELATE
більш загальним рішенням), це шлях вперед. Тоді залишається питання зняття та об'єднання цих об'єднань. Можливо, якби я міг генерувати послідовність лише дотиків полігонів, я міг би з'єднатись із цим.
Оновлення II
Цей, здається, працює для вибору ліній спільного використання полігонів (але не кутів) і, таким чином, є більш загальним рішенням, ніж вищевказаний MULTIPOLYGON
тест. Мій пункт, де зараз виглядає так:
WHERE
ST_Touches( t1.geom, t2.geom )
AND t1.geom && t2.geom
-- 'overlap' relation
AND ST_Relate(t1.geom, t2.geom)='FF2F11212') t2
Тепер залишається, як зробити злиття для більше, ніж просто пари багатокутників, але для довільного числа, що відповідає критеріям, за один раз.
ST_IntersectionArray
[функції] [1] для роботи з ST_Union [1]: gis.stackexchange.com/a/60295/36886