Mam tabelę PostGIS polygon_b
z kilkoma funkcjami wielokąta. Istnieje również tabela, polygon_a
która zawiera te same wielokąty, polygon_b
ale z niewielkimi zmianami. Teraz chcę utworzyć linie w celu wizualizacji różnic między elementami wielokąta.
Przypuszczam, że ST_ExteriorRing
i ST_Difference
będzie wykonać zadanie, ale WHERE wydaje się być dość trudne.
CREATE VIEW line_difference AS SELECT
row_number() over() AS gid,
g.geom::geometry(LineString, yourSRID) AS geom
FROM
(SELECT
(ST_Dump(COALESCE(ST_Difference(ST_ExteriorRing(polygon_a.geom), ST_ExteriorRing(polygon_b.geom))))).geom AS geom
FROM polygon_a, polygon_b
WHERE
-- ?
) AS g;
Czy ktoś może mi pomóc?
EDYCJA 1
Jak napisałem przez „tilt”, próbowałem, ST_Overlaps(polygon_a.geom, polygon_b.geom) AND NOT ST_Touches(polygon_a.geom, polygon_b.geom)
ale wynik nie jest zgodny z oczekiwaniami.
CREATE VIEW line_difference AS SELECT
row_number() over() AS gid,
g.geom::geometry(LineString, your_SRID) AS geom
FROM
(SELECT
(ST_Dump(COALESCE(ST_Difference(ST_ExteriorRing(polygon_a.geom), ST_ExteriorRing(polygon_b.geom))))).geom AS geom
FROM polygon_a, polygon_b
WHERE
ST_Overlaps(polygon_a.geom, polygon_b.geom) AND NOT ST_Touches(polygon_a.geom, polygon_b.geom))
AS g;
EDYCJA 2
workupload.com/file/J0WBvRBb (przykładowy zestaw danych)
Próbowałem zamienić wielokąty w multilinie przed użyciem ST_Difference, ale wyniki są nadal dziwne.
CREATE VIEW multiline_a AS SELECT
row_number() over() as gid,
ST_Union(ST_ExteriorRIng(polygon_a.geom))::geometry(multilinestring, 4326) AS geom
FROM
polygon_a;
CREATE VIEW multiline_b AS SELECT
row_number() over() as gid,
ST_Union(ST_ExteriorRIng(polygon_b.geom))::geometry(multilinestring, 4326) AS geom
FROM
polygon_b;
CREATE VIEW line_difference AS SELECT
row_number() over() as gid,
g.geom
FROM
(SELECT
(ST_Dump(COALESCE(ST_Difference(multiline_a.geom, multiline_b.geom)))).geom::geometry(linestring, 4326) AS geom
FROM
multiline_a, multiline_b)
As g;
qgis
postgis
polygon
linestring
differences
Morze Księżycowe
źródło
źródło
Odpowiedzi:
Oto kilka nowych sztuczek, wykorzystujących:
EXCEPT
aby usunąć geometrie z obu tabel, które są takie same, abyśmy mogli skupić się tylko na geometriach unikalnych dla każdej tabeli (A_only
iB_only
).ST_Snap
aby uzyskać dokładne węzły dla operatorów nakładek.ST_SymDifference
operatora nakładki, aby znaleźć różnicę symetryczną między dwoma zestawami geometrii, aby pokazać różnice. Aktualizacja :ST_Difference
pokazuje ten sam wynik dla tego przykładu. Możesz wypróbować dowolną funkcję, aby zobaczyć, co otrzymują.To powinno uzyskać to, czego oczekujesz:
Aby jeszcze bardziej rozpakować tę odpowiedź, pierwszym krokiem
ST_Boundary
jest określenie granicy każdego wielokąta, a nie tylko jego zewnętrznej powierzchni. Na przykład, jeśli byłyby dziury, byłyby one śledzone przez granicę.EXCEPT
Warunek służy do usuwania geometrii z A, które stanowią część B i rzędów z B, które stanowią część A. zmniejsza liczbę wierszy, które są tylko część A i część B tylko. Na przykład, aby uzyskać A_only:Oto 6 wierszy A_only i 3 wiersze B_only:
Następnie
ST_Union(DISTINCT A_only.geom)
służy do łączenia linii w jedną geometrię, zazwyczaj MultiLineString.ST_Snap służy do przyciągania węzłów z jednej geometrii do drugiej. Na przykład
ST_Snap(A, B, tol)
weźmie geometrię A i doda więcej węzłów z geometrii B lub przeniesie je do geometrii B, jeśli znajdują się wtol
odległości. Prawdopodobnie istnieje kilka sposobów korzystania z tych funkcji, ale chodzi o uzyskanie współrzędnych z każdej geometrii, które są do siebie dokładne. Dwie geometrie po przyciągnięciu wyglądają tak:I pokazać różnice, można wybrać albo
ST_SymDifference
alboST_Difference
. Oba pokazują ten sam wynik dla tego przykładu.źródło
Myślę, że jest to trochę skomplikowane, z powodu różnych zestawów węzłów obu twoich wielokątów (zielony wielokąt A, czerwony różne segmenty polionu B). Porównanie segmentów obu wielokątów daje wskazówkę, które segmenty wielokąta B zostaną zmodyfikowane.
Węzły wielokąta A
Węzły „różnych” segmentów wielokąta B
Niestety pokazuje to tylko różnicę w strukturze segmentu, ale mam nadzieję, że jest to punkt wyjścia i działa tak:
Po pobraniu i rozpakowaniu zaimportowałem zestaw danych za pomocą PostgrSQL 9.46, PostGIS 2.1 pod Debian Linux Jessie z poleceniami.
Zakładając, że segmentów wielokąta A nie ma w B i vice vera, staram się budować różnicę między segmentami obu zestawów wielokątów, pomijając przynależność segmentu do wielokątów w każdej grupie (A lub B). Z powodów dydaktycznych formułuję SQL w kilku widokach.
Odpowiadając temu postowi GIS-SE , rozkładam oba wielokąty na tabele segmentów
segments_a
isegments_b
Wielokąt A tabeli segmentów:
Tę samą procedurę zastosowano do wielokąta B.
Wielokąt B tabeli segmentów
Mogę zbudować widok tabeli różnic o nazwie
segments_diff_{a,b}
. Różnica wynika z braku posortowanych punktów początkowych lub końcowych w zestawie segmentów A i B.I rzeczy uzupełniające:
Wniosek: Aby uzyskać właściwy wynik dla małych małych segmentów oznaczonych czerwoną strzałką, oba wielokąty muszą mieć taką samą strukturę węzła i wymagany jest krok przecięcia na poziomie węzła (wstawienie wierzchołków wielokąta A w B). Skrzyżowanie może być wykonane przez:
Ale z dziwnymi wynikami ...
źródło
Patrząc na przykład, zmiana sugeruje, że funkcje z nowej tabeli, które zostały zmienione, zawsze będą się nakładać na funkcje ze starej tabeli. Dlatego skończyłbyś
Negacja dotyku polega na tym, że obiekty nakładają się również, jeśli tylko ich granice dzielą te same położenia wierzchołków.
źródło