Trovare poligoni a livello di programmazione> 90% sovrapposti da un altro strato poligonale vettoriale usando QGIS?


9

Livelli di esempio

Sto cercando di capire come usare Python per estrarre i poligoni in un vettore che sono sovrapposti di> 90% da un altro vettore. Vorrei quindi avere un vettore / mappa che mostrerà solo quei poligoni. L'immagine di esempio mostra i miei livelli. Voglio tutti i poligoni grigi che sono> 90% rossi.

Devo fare tutto questo tramite Python (o metodi similmente automatizzati). Ho ~ 1000 mappe per elaborare allo stesso modo.


Vuoi fare una 'unione' sovrapposta (vedi infogeoblog.wordpress.com/2013/01/08/geo-processing-in-qgis per alcune basi) quindi per ogni poligono originale calcola le statistiche 'in' e 'out' gis.stackexchange.com/questions/43037/… per determinare la percentuale di overlay ... suggerimento: è necessario disporre di una misurazione dell'area gis.stackexchange.com/questions/23355/…
Michael Stimson

Grazie per i suggerimenti Questo è lo stesso approccio che stavo solo tentando. Posso fare l'unione attraverso la console di Python abbastanza facilmente. Già aggiunto nei valori dell'attributo area. È il prossimo passo di cui non sono sicuro. Come posso usare Python per calcolare le statistiche 'in' e 'out' in modo da poter identificare / selezionare / tagliare ecc. I poligoni> 90%?
anormale

Penso che sia possibile senza Python. Ti serve assolutamente Python o una soluzione con livelli virtuali fa al caso tuo?
Pierma,

Le aree "in" avranno attributi da entrambi i poligoni, le aree "out" avranno solo attributi da un set di poligoni. Ottieni entrambi i set di statistiche di area e unisciti ai poligoni originali, aggiungi un campo per "in", "out" e copertura, calcola i valori di "in" e "out" dalla somma delle aree, quindi dividi "in" per " l'area originale (o 'in' + 'out') per calcolare la percentuale.
Michael Stimson,

1
Pierma - Ho solo bisogno di un metodo automatizzato per trovare i poligoni.
anormale

Risposte:


3

Il prossimo codice funziona nella mia console Python di QGIS. Produce uno strato di memoria con poligoni che sono> 90% sovrapposti da aree rosse.

mapcanvas = iface.mapCanvas()

layers = mapcanvas.layers()

#for polygon_intersects
feats_lyr1 = [ feat for feat in layers[0].getFeatures() ]

#for xwRcl
feats_lyr2 = [ feat for feat in layers[1].getFeatures() ]

selected_feats = []

for i, feat1 in enumerate(feats_lyr1):
    area1 = 0
    area2 = 0
    for j, feat2 in enumerate(feats_lyr2):
        if feat1.geometry().intersects(feat2.geometry()):
            area = feat1.geometry().intersection(feat2.geometry()).area()
            print i, j, area, feat2.attribute('class')
            if feat2.attribute('class') == 1:
                area1 += area
            else:
                area2 += area
    crit = area1/(area1 + area2)
    print crit
    if crit > 0.9:
        selected_feats.append(feat1)

epsg = layers[0].crs().postgisSrid()

uri = "Polygon?crs=epsg:" + str(epsg) + "&field=id:integer""&index=yes"

mem_layer = QgsVectorLayer(uri,
                           "mem_layer",
                           "memory")

prov = mem_layer.dataProvider()

for i, feat in enumerate(selected_feats):
    feat.setAttributes([i])

prov.addFeatures(selected_feats)

QgsMapLayerRegistry.instance().addMapLayer(mem_layer)

Ho provato il codice con questi due livelli vettoriali:

inserisci qui la descrizione dell'immagine

Dopo aver eseguito il codice nella console Python di QGIS, per risultati corroboranti, sono stati stampati gli indici i, j delle caratteristiche coinvolte, le aree di intersezione, l'attributo del campo in polygons_intersects (1 per le aree rosse e 2 per le aree grigie) e il criterio di sovrapposizione .

0 0 9454207.56892 1
0 1 17429206.7906 2
0 2 10326705.2376 2
0 4 40775341.6814 1
0 5 26342803.0964 2
0 7 11875753.3216 2
0.432253120382
1 6 1198411.02558 2
1 7 1545489.96614 2
1 10 27511427.9909 1
0.90930850584
2 7 750262.940888 2
2 8 12012343.5859 1
0.941213972294
3 6 23321277.5158 2
0.0

Il livello di memoria creato (funzioni verdi) può essere osservato nell'immagine successiva. Era come previsto.

inserisci qui la descrizione dell'immagine


6

Qui una soluzione che non richiede Python.

Aggiungi un nuovo livello virtuale con una query come:

WITH r AS (
SELECT 
    Basins800.rowid AS idGray, 
    area(Basins800.geometry) AS areaGray, 
    area(Intersection(Basins800.geometry, Severity.geometry)) AS aeraInter, 
    Basins800.geometry AS geomGray 
  FROM Basins800, Severity
)

SELECT *, areaInterSum/areaGray  AS overlap , geomGray 
    FROM (
        SELECT 
           idGray, 
           areaGray, 
           sum(areaInter) AS areaInterSum, 
           geomGray 
        FROM r 
        GROUP BY idGray) 
     WHERE areaInterSum/areaGray > 0.9

Con :

  • Basins800 come livello che vuoi filtrare con poligoni grigi

  • Gravità: sovrapposizione del livello rosso.

Il risultato sarà un nuovo livello con solo tutti i ploligoni grigi> 90% sovrapposti da poligoni rossi, con un nuovo campo contenente la percentuale di sovrapposizione.

inserisci qui la descrizione dell'immagine

Spero che funzioni. Posso aggiungere ulteriori dettagli sulla query, se necessario.

Nota: i tuoi dati contengono poligoni molto piccoli (provenienti dall'elaborazione raster e corrispondenti a un pixel raster (nella foto, possiamo vedere 4 poligoni ma ci sono altri 25 poligoni piccoli). Questo rende l'esecuzione della query molto lenta (funzione di intersezione genera una funzione per ogni coppia di funzioni dai due livelli).


Ricevo un errore quando eseguo la query tramite il pulsante "crea un livello virtuale". "Errore di esecuzione della query su CREATE TEMP VIEW _tview AS WITH r AS (" .... resto del codice qui ... seguito da: "1 - vicino a" WITH ": errore di sintassi" Sono abbastanza nuovo in QGIS. Posso creare questo livello virtuale a livello di codice? Grazie per il vostro aiuto!
anormale

Ecco un link per scaricare gli shapefile: link
anormale

Scusa, una brutta copia tra grigio e grigio (scusate il mio inglese approssimativo). Ho modificato la query. Dovrebbe funzionare ora. Perché vuoi creare il layer in modo programmatico? Il vantaggio del livello virtuale è che non è distruttivo e, se modifichi i tuoi dati (i poligoni grigi o rossi), il livello virtuale si aggiornerà automaticamente.
Pierma,

Questo è solo un piccolo pezzo del processo. Ho ~ 1000 di queste mappe da fare, quindi automatizzare il processo sarà estremamente utile.
anormale

Ricevo ancora lo stesso errore -> "1 - vicino a" WITH ": errore di sintassi". Ho inserito i nomi locali per ogni livello per grayLayer e redLayer. Il nome locale è quello che dovrei usare? vale a dire: il livello grigio è etichettato come "Basins_800", quindi ho un codice come "Basins_800.geometry"
anomalo

2

Dopo aver visto il collegamento ai shapefile Severity e Basins800 , sono riuscito a capire il geoprocesso necessario. Ho modificato il codice in:

Trovare poligoni a livello di programmazione> 90% sovrapposti da un altro strato poligonale vettoriale usando QGIS?

per ottenere questo:

mapcanvas = iface.mapCanvas()

layers = mapcanvas.layers()

#for Severity
feats_lyr1 = [ feat for feat in layers[0].getFeatures() ]

#for Basins800
feats_lyr2 = [ feat for feat in layers[1].getFeatures() ]

selected_feats = []

print "processing..."

for i, feat1 in enumerate(feats_lyr1):
    for j, feat2 in enumerate(feats_lyr2):
        if feat1.geometry().intersects(feat2.geometry()):
            area1 = feat1.geometry().intersection(feat2.geometry()).area()
            area2 = feat1.geometry().area()
            print i, j, area1, area2
    crit = area1/area2
    print crit
    if crit > 0.9:
        selected_feats.append(feat1)

epsg = layers[0].crs().postgisSrid()

uri = "Polygon?crs=epsg:" + str(epsg) + "&field=id:integer""&index=yes"

mem_layer = QgsVectorLayer(uri,
                           "mem_layer",
                           "memory")

prov = mem_layer.dataProvider()

for i, feat in enumerate(selected_feats):
    feat.setAttributes([i])

prov.addFeatures(selected_feats)

QgsMapLayerRegistry.instance().addMapLayer(mem_layer)

Dopo aver eseguito il codice, con questi shapefile nella console Python di QGIS, in pochi minuti ho ottenuto un risultato simile a Pierma ; dove il livello di memoria aveva 31 caratteristiche (diverse da 29 poligoni ottenute da lui).

inserisci qui la descrizione dell'immagine

Non eseguirò il debug dei risultati perché ci sono interazioni 1901 * 3528 = 6706728 per le funzionalità. Tuttavia, il codice sembra promettente.

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.