Wie beziehe ich mich im Feldrechner auf eine andere Ebene?

26

Gibt es eine Möglichkeit, ein Attribut aus einer Polygonebene auszuwählen und den Wert mit "inside" im Feldrechner in ein virtuelles Feld einer Punktebene einzufügen?

CASE
 WHEN within($geometry, geometry_polygon) THEN attribute_polygon
END

Bildbeschreibung hier eingeben

Mondmeer
quelle
1
Verwenden Sie dazu das Plugin 'Point Sampling Tool'.
Jakob
Weil ich dynamische Updates benötige, wenn ich neue Punkte erstelle oder vorhandene Punkte verschiebe.
Lunar Sea
Es ist besser, wenn Sie diese Interaktion per Skript ausführen, als sich auf standardmäßige Tools zu verlassen.
Nagytech
Leider habe ich keine Skripterfahrung.
Lunar Sea
@LunarSea Ich habe unten ein Beispiel für Sie geschrieben, dem Sie folgen können, aber Sie müssen es möglicherweise anpassen, um Ihren Anforderungen zu entsprechen.
Nagytech

Antworten:

22

Nach der Installation des refFunctions-Plugins sind räumliche Verknüpfungen im Feldrechner verfügbar.

geomwithin(targetLayer,targetField)
Mondmeer
quelle
Plug-Ins sind viel einfacher als die Verwendung eines benutzerdefinierten Skripts. Vielen Dank!
jpmc26
geomwithin ('targetLayer', 'targetField').
Raja
19

Der Feldrechner unterstützt standardmäßig keine räumlichen Verknüpfungen zwischen Feature-Layern. Wenn Sie sich jedoch den Beitrag von NathanW im Funktionseditor für QGIS-Ausdrücke ansehen, können Sie feststellen, dass wir unsere eigene Dateninteraktion skripten können.

Mit dem folgenden Skript können Sie ausdrücken, wonach Sie suchen. Es funktioniert, indem alle Features auf der Polygonebene durchlaufen werden. Wenn eine räumliche Verknüpfung vorhanden ist, verweisen Sie auf Tabellendaten aus der angegebenen Spalte:

from qgis.core import *
from qgis.gui import *
from qgis.utils import iface

allfeatures = None
index = QgsSpatialIndex()
indexMade = 0
refLayer = None

@qgsfunction(args="auto", group='Custom')
def spatialJoinLookup(layerName, refColumn, defaultValue, geom, feature, parent):

    if geom is None:
        return defaultValue

    # globals so we don't create the index, refLayer more than once
    global allfeatures
    global index
    global indexMade
    global refLayer

    # Get the reference layer
    if refLayer is None:
        for layer in iface.mapCanvas().layers():
            if layerName == layer.name():
                refLayer = layer
                break
    if refLayer is None:
        raise Exception("Layer [" + layerName + "] not found")

    # Create the index if not exists
    if indexMade == 0:
        index = QgsSpatialIndex()
        allAttrs = layer.pendingAllAttributesList()
        layer.select(allAttrs)
        allfeatures = {feature.id(): feature for (feature) in refLayer.getFeatures()}
        for f in allfeatures.values():
            index.insertFeature(f)
        indexMade = 1

    # Use spatail index to find intersect 
    fid = None
    ids = index.intersects(geom.boundingBox())
    for id in ids:
        fid = id
        break # Only get the first match.
    if fid is not None:
        return allfeatures[fid].attribute(refColumn)

    # Default
    return defaultValue

Beispiel für eine Polygonebene

Unten sehen Sie ein Beispiel für einen Polygon-Layer, den Sie möglicherweise haben. Ich habe auch eine entsprechende Punktebene erstellt, die Sie im endgültigen Bild sehen werden.

Bildbeschreibung hier eingeben

Ausdrucksverwendung

Hinweis: Wenn Sie eine separate Spalte verwenden möchten, müssen Sie das zweite Argument so ändern, dass es mit dem Spaltennamen im Polygon-Dataset übereinstimmt. Beispiel: Sie könnten die Spalte 'AreaNumber' verwenden, müssten jedoch dem Spaltentyp in den Einstellungen des Feldrechners entsprechen.

Bildbeschreibung hier eingeben

Ergebnis

Sie können sehen, dass der Standardspaltenwert angewendet wurde, wenn keine räumliche Verknüpfung vorhanden ist und die anderen mit den korrekten Daten übereinstimmen. Beachten Sie, dass das Skript, das ich gegeben habe, nur beim ersten Spiel beitritt. Sie müssten eine andere Geschäftslogik erstellen, wenn sich Ihre Polygone überschneiden.

Bildbeschreibung hier eingeben

Nagytech
quelle
Vielen Dank, Ihr Skript funktioniert einwandfrei, wenn Sie in der ersten 'if'-Anweisung' geom 'anstelle von' geometry 'verwenden. Das Verbinden von Geometrien auf diese Weise kann sehr nützlich sein, z. B. um mehrere Beschriftungen auf Polygonen zu erstellen.
Lunar Sea
Entschuldigung, ich weiß nicht, wie ich das verpasst habe. Hoffentlich gibt es keine Leistungsprobleme - ich habe es nur mit einer sehr kleinen Teilmenge von Datensätzen versucht.
Nagytech
Mit nur über 100 Punkten kämpft QGIS mit Leistungsproblemen. Das Hinzufügen eines neuen Punkt-Features ist wirklich ein Problem, auch wenn im aktuellen Canvas-Bereich kein Punkt-Feature angezeigt wird. Andernfalls wird beim Einzoomen QGIS beschleunigt. Ich habe 'CASE WHEN $ scale <10000 THEN spaciousJoinLookupI (' Polygons ',' AreaName ',' None ', $ geometry) END' ausprobiert, aber es funktioniert nicht. Kann ich etwas tun, um die Leistung zu verbessern?
Lunar Sea
@LunarSea Ich habe die Funktion aktualisiert, um einen räumlichen Index zu verwenden. Es sollte einigermaßen schneller sein.
Nagytech
Danke für Ihre Hilfe. Die räumliche Verbindung ist jetzt viel schneller, aber leider funktioniert etwas nicht richtig. Ich erhalte unterschiedliche Ergebnisse für Punkte innerhalb ein und desselben Polygons.
Lunar Sea
8

Dies kann im Feldrechner mit Funktion durchgeführt werden aggregate(). Erstellen Sie in der Punktebene ein neues Feld mit dem folgenden Ausdruck für den Feldrechner:

aggregate(
layer:= 'polygon_layer_name',
aggregate:='concatenate',
expression:=joining_field_name,
concatenator:=', ',
filter:=intersects($geometry, geometry(@parent))
)

Wo layerist Polygon-Layer-Name wie Zeichenfolge geschrieben, aggreagateist Aggregatfunktion (kann auch Summe usw. verwendet werden), expressionwird Feld aus Werten genommen, concatenatorwird Zeichenfolge zusammengefügt (muss auch in diesem Fall gesetzt werden) und filterbasiert auf Filterfunktionen on expression (schneidet in diesem Fall die Ebenengeometrie mit der Geometrie der übergeordneten Ebene).

Weitere Informationen finden Sie in der Dokumentation zu Aggregates QGIS .

Für automatische Aktualisierungen können virtuelle Felder verwendet werden oder Sie können den Ausdruck als Standardwert in den Formulareinstellungen für Attribute in den Layereigenschaften festlegen ( Dokumentation zu den Formulareinstellungen für Attribute ).

Bildbeschreibung hier eingeben

Oto Kaláb
quelle
2
Es ist zu beachten, dass räumliche Funktionen (mit geometry(@parent)) erst ab QGIS 3 unterstützt werden. Nur für den Fall, dass jemand, der dies liest, immer noch 2.18 verwendet ...
she_weeds
Vielen Dank. Klappt wunderbar.
Spatialthoughts