Chciałbym wykonać testy przylegania na warstwie działki (wielokątów) i scalić je, jeśli spełniają określone kryteria (mogą być wielkości). Na poniższym zdjęciu chciałbym scalić wielokąty 1,2,3 i 4, ale nie 5.
Mam dwa problemy:
ST_TOUCHES
zwraca PRAWDA, jeśli dotykają się tylko narożniki, a nie segment linii. Myślę, że potrzebuję ST_RELATE, aby sprawdzić segmenty linii wspólnej.- Idealnie chciałbym scalić WSZYSTKIE sąsiadujące wielokąty w jeden, ale nie jestem pewien, jak skalować poza dwa - jak w, scalić 1,2,3 i 4 (i prawdopodobnie więcej na temat rzeczywistych danych) w jednej rundzie.
Struktura, którą mam teraz, opiera się na samodzielnym połączeniu ST_TOUCHES
.
Dane dotyczące zabawek
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 ;
Wybór
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
Oto wynik:
+-----+---------+-------------------------------------------------------------------------------+
| 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))) |
+-----+---------+-------------------------------------------------------------------------------+
Zauważ, że wielokąt id = 3 dzieli punkt z id = 1 i dlatego jest zwracany jako wynik dodatni. Jeśli zmienię klauzulę WHERE na, ST_Touches( t1.geom, t2.geom ) AND t1.geom && t2.geom AND ST_Relate(t1.geom, t2.geom ,'T*T***T**');
nie otrzymam żadnych zapisów.
Po pierwsze , jak określić ST_Relate, aby upewnić się, że brane są pod uwagę tylko paczki dzielące segment linii.
A potem, jak mam połączyć wielokąty 1,2,3,4 w jednej rundzie, zwijając wyniki z powyższego wezwania, jednocześnie uznając, że przyleganie 1 do 2 jest takie samo jak odwrotność?
Aktualizacja
Jeśli dodam to do where
klauzuli, oczywiście otrzymam tylko wielokąty, a nie wieloboki, eliminując w ten sposób fałszywe pozytywy dla moich celów - szlifowanie narożników zostanie zignorowane.
GeometryType(st_union(t1.geom,t2.geom)) != 'MULTIPOLYGON'
Chociaż nie jest to idealne (wolałbym używać sprawdzeń topologii ST_RELATE
jako bardziej ogólnego rozwiązania), jest to krok naprzód. Pozostaje zatem kwestia odszyfrowania i połączenia ich. Być może, gdybym mógł wygenerować sekwencję dla dotykających się tylko wielokątów, mógłbym się z tym połączyć.
Aktualizacja II
Ten wydaje się działać do wyboru wielokątów dzielących linie (ale nie narożniki), a zatem jest bardziej ogólnym rozwiązaniem niż powyższy MULTIPOLYGON
test. Moja klauzula where wygląda teraz tak:
WHERE
ST_Touches( t1.geom, t2.geom )
AND t1.geom && t2.geom
-- 'overlap' relation
AND ST_Relate(t1.geom, t2.geom)='FF2F11212') t2
Teraz pozostaje tylko to, jak wykonać scalenie dla więcej niż tylko pary wielokątów, ale dla dowolnej liczby pasującej do kryteriów za jednym razem.
ST_IntersectionArray
[funkcję] [1] do pracy ze ST_Union [1]: gis.stackexchange.com/a/60295/36886