Percentuale di poligono in un file di forma all'interno di un poligono di un altro


13

Sono un novizio, mi scuso se questo è ovvio / è già stato chiesto e risposto ma non sono riuscito a trovare nulla.

Ho due shapefile: 1. uno strato di confine amministrativo per una contea del Regno Unito noto come confine LSOA che contiene 500 piccole zone 2. una zona di inondazione.

Idealmente, voglio scoprire quali delle piccole zone LSOA sono ≥50% all'interno della zona di inondazione e finire con un sì / no o un 1/0 per ciascuna delle 500 zone LSOA.

Ma non so come farlo. Ho pensato di poter unire i due shapefile, ma non c'è alcun attributo comune tra loro. Quindi ho pensato di poter usare la funzione Join Attribute by Location, che ha funzionato e mi mostra quali LSOA si trovano nella zona di inondazione, ma è quasi tutto (vedi immagine 2).

Penso che questo sia un problema SQL ma non lo so. Sono nuovo di QGIS e non ho mai usato PostgreSQL.

Qualsiasi aiuto sarebbe molto apprezzato. Posso fornirti tutte le informazioni di cui hai bisogno per aiutarmi.

inserisci qui la descrizione dell'immagine

inserisci qui la descrizione dell'immagine

Risposte:


11

Questo è un compito relativamente semplice usando gli strumenti di geoprocessing inclusi in QGIS.

  1. Calcola l'area delle tue zone LSOA.

    • Aprire la tabella degli attributi del livello LSOA.
    • Abilita la modalità di modifica.
    • Apri il calcolatore di campo.
    • Crea un nuovo campo di tipo "Numero decimale (reale)" con l'espressione "$ area".
    • Disabilita la modalità di modifica (salvataggio delle modifiche).
  2. Unisci il livello della zona di alluvione in un'unica funzione multiparte.

    • Vector > Geometry Tools > Singleparts to Multipart.
    • Seleziona "--- Unisci tutto ---" per il campo ID univoco.
  3. Intersecare lo strato di zona LSOA con lo strato di zona di alluvione multipart.

    • Vector > Geoprocessing Tools > Intersect.
    • Il livello di input è rappresentato dalle zone LSOA, il livello di intersezione è rappresentato dalle zone di inondazione.
  4. Il livello risultante sarà costituito dalle parti delle zone LSOA (con gli attributi dal livello zone LSOA) che si sovrapponevano al livello zone alluvione. Per calcolare la proporzione di ciascuna zona LSOA all'interno di una zona di inondazione:

    • Calcola l'area delle feature intersecate (come nel passaggio n. 1), quindi
    • Aggiungi un altro campo, dividendo l'area (totale) originale per l'area intersecata. Il risultato è un decimale tra 0 e 1. Moltiplicare per 100 per dare una percentuale.
  5. Unire il livello LSOA originale al livello intersecato, utilizzando l'ID univoco condiviso da entrambi i livelli.

  6. Esporta il livello unito come nuovo file di forma.

  7. Elimina gli attributi duplicati.

Et voilà!

Senza il passaggio n. 2, verrebbe creata una singola funzione per ciascuna caratteristica della zona di alluvione diversa per ciascuna caratteristica LSOA. Questo probabilmente non è quello che vuoi se sei interessato solo alla copertura totale per ogni zona LSOA. Se si desidera distinguere tra inondazioni fluviali / maree / pluviali (e i dati della zona di alluvione lo supportano), è possibile convertire le singole parti in più parti specificando il campo "TIPO" come campo ID univoco.


Grazie per l'aiuto! Molto apprezzato. Tuttavia, ho qualche problema. Ho seguito i passaggi. Il passaggio 3, l'Intersect, ha richiesto 10 ore per essere completato e quando è stato fatto tutto quello che ho avuto è stato un file di forma vuoto: i.imgur.com/QIM6Gtg.png C'è qualcosa che mi sono perso? Ho provato a completare il processo ed eseguire il passaggio 4 ma non ci sono dati per calcolare l'area dell'intersezione.
KJGarbutt,

Ho avuto problemi a fare intersezioni con strati di inondazione prima. Le funzionalità sono grandi e complicate. Il modo in cui ci ho lavorato in passato è quello di dividerli in caratteristiche più piccole, in modo che l'indice spaziale possa fare più lavoro. Per fare ciò, creare una griglia vettoriale della stessa misura del livello flood ( Vector > Research Tools > Vector Grid... Output grid as polygons), quindi intersecare la griglia con il livello flood. Quindi utilizzare l'output invece del livello flood nel passaggio 3. Immagino che il motivo per cui il layer fosse vuoto sia dovuto al crash.
Snorfalorpagus,

Grazie ancora. L'unico problema ora è che QGIS si arresta in modo anomalo ogni volta che provo a creare la griglia vettoriale. Ho seguito il consiglio da qui, ma si blocca ogni volta. Ho modificato i parametri più volte e ho provato solo a utilizzare lo shapefile della zona di inondazione, invece di aprire l'intero file di progetto e non funziona ogni volta. Qualche idea? ! Schermata qui .
KJGarbutt,

I parametri X e Y che hai specificato sono troppo piccoli. Prova qualcosa come 1000 x 1000. Puoi anche farlo più volte, cioè prima 5000 x 5000, usa l'output per creare 500 x 500. Vedi la relativa risposta qui: gis.stackexchange.com/a/66319/12420
Snorfalorpagus

L'ho quasi risolto con il tuo aiuto! Tuttavia, quando vado a unire il livello LSOA originale con il livello intersecato, perdo molti dati. Penso che sia perché alcuni dei quadrati della griglia vettoriale creati rientrano nella stessa area LSOA e quindi hanno lo stesso codice LSOA di ciascuno. Quindi, finisco con 2+ percentuali per ogni area LSOA quando faccio l'unione e mi sembra di averne solo una. C'è un modo per sommare ogni percentuale per ogni quadrato della griglia vettoriale con lo stesso LSOA?
KJGarbutt,

6

È possibile utilizzare spatialite e alcune funzioni spaziali 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

Sembra qualcosa che potrebbe essere fatto molto più facilmente delle risposte presentate. Vorrei usare un semplice script Python personalmente:

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)

questo valuta solo i poligoni di inondazione che si intersecano con il riquadro di delimitazione di ciascun livello di lavanderia, quindi dovrebbe essere abbastanza veloce da eseguire, quindi aggiorna solo un campo nel livello esistente (invece di un'operazione complessa di creazione di un livello completamente nuovo e copia di vecchi valori quindi eliminando)


2

Ho avuto lo stesso problema di KJ seguendo le istruzioni di Snorfalorpagus usando il metodo "Intersect" nel passaggio 3. Ci è voluto un po 'di tempo per calcolare e ciò che mi è rimasto era vuoto.

Ho provato a seguire gli stessi passaggi ad eccezione dell'utilizzo del metodo "Clip" in QGIS invece di Intersect - quindi, nel tuo esempio, ciò che rimarrebbe sarebbero le parti delle aree NON coperte dalla zona di alluvione. Questo ha funzionato per qualche motivo e sono stato in grado di utilizzare il calcolo del campo "Area" dal passaggio precedente, oltre a un nuovo calcolo "Area" sulle parti rimanenti di ciascun poligono, per capire la% di ogni area che NON era coperto dall'altro strato poligonale.

Questo è tecnicamente il contrario di ciò che hai chiesto. Ma da lì si tratta solo di sottrarre ogni valore da 1 per ottenere ciò che è coperto dalla zona di inondazione.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.