Mit QGIS programmgesteuert Polygone finden, die zu> 90% von einer anderen Vektorpolygonschicht überlappt werden?

9

Beispielschichten

Ich versuche herauszufinden, wie man mit Python die Polygone in einem Vektor extrahiert, die von einem anderen Vektor um> 90% überlappt werden. Ich hätte dann gerne einen Vektor / eine Karte, die nur diese Polygone zeigt. Das Beispielbild zeigt meine Ebenen. Ich möchte alle grauen Polygone, die> 90% rot sind.

Ich muss dies alles über Python (oder ähnlich automatisierte Methoden) tun. Ich habe ~ 1000 Karten, um auf die gleiche Weise zu verarbeiten.

dnormous
quelle
Sie möchten eine Overlay-Union erstellen ( einige Informationen finden Sie unter infogeoblog.wordpress.com/2013/01/08/geo-processing-in-qgis ). Berechnen Sie dann für jedes Originalpolygon die Statistiken "In" und "Out" gis.stackexchange.com/questions/43037/… , um den Überlagerungsprozentsatz zu bestimmen ... Hinweis: Sie benötigen eine Flächenmessung gis.stackexchange.com/questions/23355/…
Michael Stimson
Danke für die Tipps. Das ist der gleiche Ansatz, den ich gerade versucht habe. Ich kann die Vereinigung einfach genug über die Python-Konsole durchführen. Bereits in den Bereichsattributwerten hinzugefügt. Es ist der nächste Schritt, bei dem ich mir nicht sicher bin. Wie berechne ich mit Python die Statistiken "In" und "Out", damit ich die> 90% -Polygone identifizieren / auswählen / ausschneiden usw. kann?
dnormous
Ich denke, es ist ohne Python möglich. Benötigen Sie unbedingt Python oder eine Lösung mit virtuellen Ebenen ist gut für Sie?
Pierma
Die 'In'-Bereiche haben Attribute aus beiden Polygonen, die' Out'-Bereiche haben nur Attribute aus einem Satz von Polygonen. Holen Sie sich beide Sätze von Flächenstatistiken und verbinden Sie sich wieder mit den ursprünglichen Polygonen, fügen Sie ein Feld für 'in', 'out' und Abdeckung hinzu, berechnen Sie die Werte für 'in' und 'out' aus der Summe der Flächen und dividieren Sie 'in' durch die ursprüngliche Fläche (oder 'in' + 'out') zur Berechnung des Prozentsatzes.
Michael Stimson
1
Pierma - Ich brauche nur eine automatisierte Methode, um die Polygone zu finden.
dnormous

Antworten:

3

Der nächste Code funktioniert in meiner Python-Konsole von QGIS. Es wird eine Speicherschicht mit Polygonen erzeugt, die zu> 90% von roten Bereichen überlappt sind.

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)

Ich habe den Code mit diesen beiden Vektorebenen ausprobiert:

Geben Sie hier die Bildbeschreibung ein

Nachdem der Code in der Python-Konsole von QGIS ausgeführt wurde, wurden zur Bestätigung der Ergebnisse die Indizes i, j der beteiligten Features, Schnittbereiche, Feldattribute in polygons_intersects (1 für rote Bereiche und 2 für graue Bereiche) und das Überlappungskriterium gedruckt .

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

Die erstellte Speicherschicht (grüne Merkmale) kann beim nächsten Bild beobachtet werden. Es war wie erwartet.

Geben Sie hier die Bildbeschreibung ein

xunilk
quelle
5

Hier eine Lösung, die kein Python benötigt.

Fügen Sie eine neue virtuelle Ebene mit einer Abfrage wie der folgenden hinzu:

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

Mit:

  • Basins800 als Ihre Ebene möchten Sie mit grauen Polygonen filtern

  • Schweregrad: Ihre rote Schicht überlappt sich.

Das Ergebnis ist eine neue Schicht, in der nur alle grauen Plolygone> 90% von roten Polygonen überlappt werden. Ein neues Feld enthält den Überlappungsprozentsatz.

Geben Sie hier die Bildbeschreibung ein

Hoffe das funktioniert. Ich kann bei Bedarf weitere Details zur Abfrage hinzufügen.

Hinweis: Ihre Daten enthalten sehr kleine Polygone (die aus Ihrer Rasterverarbeitung stammen und einem Rasterpixel entsprechen (auf dem Bild sehen Sie 4 Polygone, aber es gibt 25 andere kleine Polygone). Dadurch wird die Ausführung der Abfrage sehr langsam (Schnittfunktion) generiert ein Feature für jedes Feature-Paar aus den beiden Ebenen).

Pierma
quelle
Ich erhalte eine Fehlermeldung, wenn ich die Abfrage über die Schaltfläche "Virtuelle Ebene erstellen" ausführe. "Abfrageausführungsfehler in CREATE TEMP VIEW _tview AS WITH r AS (" .... Rest des Codes hier ... gefolgt von: "1 - in der Nähe von" WITH ": Syntaxfehler" Ich bin ziemlich neu in QGIS. Kann ich Erstellen Sie diese virtuelle Ebene programmgesteuert? Vielen Dank für Ihre Hilfe!
dnormous
Hier ist ein Link zum Herunterladen der Shapefiles: Link
dnormous
Entschuldigung, eine schlechte Kopie zwischen Grau und Grau (Entschuldigung für mein ungefähres Englisch). Ich habe die Abfrage bearbeitet. Es sollte jetzt funktionieren. Warum möchten Sie die Ebene progamatisch erstellen? Der Vorteil der virtuellen Ebene besteht darin, dass sie nicht destruktiv ist. Wenn Sie Ihre Daten (die grauen oder roten Polygone) bearbeiten, wird die virtuelle Ebene automatisch aktualisiert.
Pierma
Dies ist nur ein kleiner Teil des Prozesses. Ich habe ~ 1000 dieser Karten zu erledigen, daher ist die Automatisierung des Prozesses äußerst hilfreich.
dnormous
Ich erhalte immer noch den gleichen Fehler -> "1 - in der Nähe von" WITH ": Syntaxfehler". Ich habe die lokalen Namen für jede Ebene für die greyLayer und die redLayer eingefügt. Ist der lokale Name das, was ich verwenden sollte? Das heißt: Die graue Ebene ist als "Basins_800" gekennzeichnet, daher habe ich Code wie "Basins_800.geometry"
dnormous
2

Nachdem ich den Link zu den Shapefiles Severity und Basins800 gesehen hatte , konnte ich den erforderlichen Geoprozess verstehen. Ich habe den Code geändert in:

Mit QGIS programmgesteuert Polygone finden, die zu> 90% von einer anderen Vektorpolygonschicht überlappt werden?

für dieses bekommen:

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)

Nachdem ich den Code mit diesen Shapefiles in der Python-Konsole von QGIS ausgeführt hatte, erhielt ich in wenigen Minuten ein ähnliches Ergebnis wie Pierma . wo die Speicherschicht 31 Merkmale hatte (verschiedene von 29 Polygonen, die er bekommen hatte).

Geben Sie hier die Bildbeschreibung ein

Ich werde die Ergebnisse nicht debuggen, da es 1901 * 3528 = 6706728 Interaktionen für Features gibt. Der Code sieht jedoch vielversprechend aus.

xunilk
quelle