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/36886Odpowiedzi:
Nie mogłem przestać myśleć, że twój przykład jest w rzeczywistości rastrem i chociaż wspomniałeś, że chciałbyś się połączyć w oparciu o „określone kryteria (może to być rozmiar)”, chciałbym dać mu szansę na konwersję rastra.
W twoim konkretnym przykładzie będzie to działać:
Dzieje się tak, ponieważ ponieważ twoje wielokąty są idealnie wyrównanymi komórkami, ładnie przekształcą się w raster (rozmiar komórki 10 x 20). Dumpaspolygons pomaga ci tutaj, łącząc wszystkie sąsiednie komórki w jedną i porównując z oryginalnymi wielokątami, będziesz nawet w stanie odzyskać id dla niepołączonych poli.
Po wyjaśnieniu tego jestem bardzo ciekawy, jak to się skaluje i jak duży jest twój zestaw danych: D
źródło
Oto przykład, jak to zrobić w stylu proceduralnym z wieloma przejściami pod maską.
Powinieneś być w stanie przenosić więcej kolumn i zastosować dodatkowe kryteria łączenia, modyfikując sposób działania
LIMIT 1
poniższego wyboru:Uruchom rzecz:
Właściwe związki, bez wieloboków:
źródło
Oto kolejna (nie działająca) strategia dla odniesienia (której nie udało mi się wykluczyć przypadku pojedynczego punktu dotykowego). Powinno być szybsze niż moja inna odpowiedź, ponieważ zajmuje tylko „jedno przejście”.
(prosimy o poprawienie i opublikowanie innej odpowiedzi, jeśli ktokolwiek może uzyskać geometrię id = 5 we własnej grupie)
Aby odzyskać listę identyfikatorów itp., Musisz
st_contains
ponownie dołączyć do tabeli testpoly, jak opisano szczegółowo w następującej odpowiedzi: /programming//a/37486732/6691, ale nie mogłem tego uruchomić dla wielokątów z jakiegoś powodu.źródło
Oto szybki cios przy użyciu nieco zmodyfikowanego oryginalnego zapytania:
Odnośniki: https://postgis.net/docs/using_postgis_dbmanagement.html#DE-9IM
źródło