Procent wielokąta w jednym pliku kształtu w obrębie wielokąta innego


13

Jestem nowicjuszem, przepraszam, jeśli to oczywiste / został już zapytany i odpowiedział, ale nic nie mogłem znaleźć.

Mam dwa kształty: 1. administracyjna warstwa graniczna dla hrabstwa w Wielkiej Brytanii znana jako granica LSOA, która ma 500 małych stref 2. strefa powodziowa.

Idealnie chcę dowiedzieć się, które z małych stref LSOA znajdują się w ≥50% w strefie powodziowej i kończą na tak / nie lub 1/0 dla każdej z 500 stref LSOA.

Ale nie wiem jak to zrobić. Pomyślałem, że mogę dołączyć do dwóch plików kształtów, ale nie ma między nimi wspólnej cechy. Potem pomyślałem, że mogę użyć funkcji Dołącz atrybut według lokalizacji, która działała i pokazuje mi, które LSOA znajdują się w strefie powodzi, ale to prawie wszystkie z nich (patrz zdjęcie 2).

Myślę, że to jest problem SQL, ale nie wiem. Jestem nowy w QGIS i nigdy nie korzystałem z PostgreSQL.

Każda pomoc byłaby bardzo mile widziana. Mogę podać wszelkie informacje, których potrzebujesz, aby mi pomóc.

wprowadź opis zdjęcia tutaj

wprowadź opis zdjęcia tutaj

Odpowiedzi:


12

Jest to stosunkowo proste zadanie przy użyciu narzędzi geoprzetwarzania zawartych w QGIS.

  1. Oblicz obszar swoich stref LSOA.

    • Otwórz tabelę atrybutów warstwy LSOA.
    • Włącz tryb edycji.
    • Otwórz kalkulator pola.
    • Utwórz nowe pole typu „Liczba dziesiętna (rzeczywista)” z wyrażeniem „$ area”.
    • Wyłącz tryb edycji (zapisywanie zmian).
  2. Scal warstwę strefy zalewowej w jeden element wieloczęściowy.

    • Vector > Geometry Tools > Singleparts to Multipart.
    • Wybierz „--- Scal wszystko ---” w polu Unikatowy identyfikator.
  3. Przecinaj warstwę strefy LSOA z wieloczęściową warstwą strefy zalania.

    • Vector > Geoprocessing Tools > Intersect.
    • Warstwa wejściowa to strefy LSOA, warstwa przecinająca to strefy powodziowe.
  4. Powstała warstwa będzie częściami stref LSOA (z atrybutami z warstwy stref LSOA), które nakładają się na warstwę stref powodziowych. Aby obliczyć udział każdej strefy LSOA w strefie powodziowej:

    • Następnie oblicz obszar przeciętych elementów (jak w kroku 1)
    • Dodaj kolejne pole, dzieląc oryginalny (całkowity) obszar przez przecięty obszar. Wynikiem jest liczba dziesiętna od 0 do 1. Pomnóż przez 100, aby podać wartość procentową.
  5. Połącz oryginalną warstwę LSOA z warstwą przecinającą się, używając unikalnego identyfikatora współdzielonego przez obie warstwy.

  6. Wyeksportuj połączoną warstwę jako nowy plik kształtu.

  7. Usuń zduplikowane atrybuty.

Zrobione!

Bez kroku 2 dla każdej funkcji LSOA utworzono by oddzielną funkcję. Prawdopodobnie nie jest to, czego chcesz, jeśli interesuje Cię tylko całkowity zasięg dla każdej strefy LSOA. Jeśli chcesz rozróżnić zalew fluwialny / pływowy / pluwialny (a dane strefy powodziowej to obsługują), możesz przekonwertować pojedyncze elementy na wieloczęściowe, określając pole „TYPE” jako pole Unique ID.


Dziękuję za pomoc! Bardzo mile widziane. Mam jednak problemy. Postępowałem zgodnie z instrukcjami. Wykonanie kroku 3, przecięcie, zajęło 10 godzin, a kiedy zostało zrobione, dostałem tylko pusty plik kształtu : i.imgur.com/QIM6Gtg.png Czy coś mi umknęło? Próbowałem zakończyć proces i wykonać krok 4, ale nie ma danych do obliczenia obszaru przecięcia.
KJGarbutt

Wcześniej miałem problemy ze skrzyżowaniem z warstwami powodzi. Funkcje są duże i skomplikowane. W przeszłości pracowałam nad tym, aby podzielić je na mniejsze elementy, aby indeks przestrzenny mógł wykonać więcej pracy. Aby to zrobić, utwórz siatkę wektorową o tym samym stopniu co warstwa powodziowa ( Vector > Research Tools > Vector Grid... Output grid as polygons), a następnie przecinaj siatkę z warstwą powodziową. Następnie użyj danych wyjściowych zamiast warstwy powodziowej w kroku 3. Zgaduję, że przyczyną pustej warstwy jest to, że się zawiesiła.
Snorfalorpagus

Dzięki jeszcze raz. Jedynym problemem jest teraz to, że QGIS ulega awarii za każdym razem, gdy próbuję utworzyć siatkę wektorową. Postępowałem zgodnie z tą radą , ale za każdym razem ulega ona awarii. Zmieniłem parametry wiele razy i próbowałem tylko przy użyciu pliku kształtu strefy powodzi, zamiast otwierać cały mój plik projektu i za każdym razem kończy się to niepowodzeniem. Jakieś pomysły? ! Zrzut ekranu tutaj .
KJGarbutt

Podane parametry X i Y są zdecydowanie za małe. Spróbuj czegoś takiego jak 1000 x 1000. Możesz to zrobić nawet wiele razy, tj. Najpierw zrób 5000 x 5000, użyj danych wyjściowych, aby utworzyć 500 x 500. Zobacz pokrewną odpowiedź tutaj: gis.stackexchange.com/a/66319/12420
Snorfalorpagus

Prawie złamałem go z twoją pomocą! Kiedy jednak dołączam do oryginalnej warstwy LSOA z warstwą przecinającą się, tracę dużo danych. Myślę, że dzieje się tak, ponieważ niektóre z utworzonych kwadratów siatki wektorowej mieszczą się w tym samym obszarze LSOA, a więc mają taki sam kod LSOA jak każdy z nich. Tak więc, kiedy łączę, otrzymuję 2+ wartości procentowe dla każdego obszaru LSOA i wydaje mi się, że dostaję tylko jeden z nich. Czy istnieje sposób na zsumowanie każdego procentu dla każdego kwadratu siatki wektorowej z tym samym LSOA?
KJGarbutt

6

Możesz użyć funkcji spatialite i niektórych przestrzennych funkcji SQL.

Select t1.geometry, t1.ID, area(t1.geometry), area(t2.geometry) ...... (anything you need to have in the table results)

(area(intersection(t1.geometry,t2.geometry))) as "Commun_AREA"

, ("Commun_AREA"*100/(area(t1.geometry))) as "Percent_AREA"

From lsoa as t1, flood_zone as t2

Where Intersects( t1.geometry,t2.geometry ) = 1

3

Wydaje się, że można to zrobić o wiele łatwiej niż odpowiedzi. Osobiście użyłbym prostego skryptu python:

floodName = "the layer name here"
boundryName = "the layer name here"
fieldName = "the name of the field to contain the output 1/0"
minCoverage = 0.5 # the minimum amount of area covered to write 1
updateMap = [] # this will store values to be written    

# get layers
floodLayer = QgsMapLayerRegistry.instance().mapLayersByName(floodName)[0]
boundryLayer = QgsMapLayerRegistry.instance().mapLayersByName(boundryName)[0]
fieldIndex = boundryLayer.dataProvider().fieldNameIndex(fieldName)    

# iterate through boundries
for b in boundryLayer.getFeatures():
    # get only flood features that intersect with this feature's bounding box
    # this will make the script go way faster than it would otherwise
    request = QgsFeatureRequest().setFilterRect(b.geometry().boundingBox())
    floodGeom = geometry()
    floodFeat = QgsFeature()
    iter = floodLayer.getFeatures(request)
    iter.nextFeature(feat)
    while iter.nextFeature(feat):
        floodGeom = floodGeom.combine(feat.geometry())
    intersectGeom = b.geometry().intersection(feat.geometry())
    if intersectGeom.area() > minCoverage * b.geometry().area():
        updateMap[b.id()] = {fieldIndex : 1}
    else:
        updateMap[b.id()] = {fieldIndex : 0}

boundryLayer.dataProvider().changeAttributeValues(updateMap)

ocenia to tylko wielokąty zalewowe, które przecinają się z obwiednią każdej warstwy granicznej, więc uruchomienie powinno być dość szybkie, a następnie aktualizuje tylko jedno pole w istniejącej warstwie (zamiast złożonej operacji tworzenia całej nowej warstwy i kopiowania starych wartości następnie usuwanie)


2

Miałem ten sam problem, co KJ, postępując zgodnie z instrukcjami Snorfalorpagusa przy użyciu metody „Przecięcie” w kroku 3. Obliczenie zajęło trochę czasu, a to, co mi pozostało, było puste.

Próbowałem wykonać te same kroki, z wyjątkiem użycia metody „Klip” w QGIS zamiast przecinania - tak więc w twoim przykładzie pozostałyby części obszarów, które NIE są objęte strefą powodzi. Wydawało się, że to działa z jakiegoś powodu i mogłem skorzystać z obliczenia pola „Obszar” z poprzedniego kroku, a także nowego obliczenia „Obszar” dla pozostałych części każdego wielokąta, aby obliczyć% każdego obszaru, który NIE był pokryty drugą warstwą wielokąta.

Technicznie jest to odwrotność tego, o co prosiłeś. Ale stamtąd to tylko kwestia odjęcie każdą wartość od 1 do dostać to, co jest objęte strefą przeciwpowodziowej.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.