Come fare riferimento a un altro livello nel calcolatore di campo?


26

Esiste un modo per selezionare un attributo da un livello poligonale e inserire il valore in un campo virtuale di un livello punto usando "entro" nel calcolatore di campo?

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

inserisci qui la descrizione dell'immagine


1
Perché non utilizzare il plug-in "Point sampling tool" per questo?
Jakob,

Perché ho bisogno di aggiornamenti dinamici durante la creazione di nuovi punti o lo spostamento di punti esistenti.
Mare lunare,

Faresti meglio a scrivere script su questa interazione piuttosto che affidarti a strumenti pronti all'uso.
nagytech,

Purtroppo non ho alcuna esperienza di scripting.
Lunar Sea,

@LunarSea Ho scritto un esempio di seguito da seguire, ma potresti doverlo modificare per adattarlo alle tue esigenze.
nagytech,

Risposte:


22

I join spaziali sono disponibili nel calcolatore di campo dopo l'installazione del plug-in refFunctions.

geomwithin(targetLayer,targetField)

I plug-in sono molto più semplici rispetto all'utilizzo di uno script personalizzato. Grazie!
jpmc26,

geomwithin ( 'targetLayer', 'Target Field').
Raja

19

Immediatamente, il calcolatore di campo non supporta i join spaziali tra i layer delle funzionalità. Ma, se dai un'occhiata al post di NathanW sull'editor di funzioni per le espressioni qgis , sarai in grado di capire che possiamo scrivere la nostra interazione con i dati.

Il seguente script ti consentirà di esprimere ciò che stai cercando. Funziona ripetendo tutte le funzionalità sul layer poligonale e se esiste un join spaziale, fai riferimento ai dati tabulari dalla colonna specificata:

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

Esempio di strato poligonale

Di seguito è riportato un esempio di un livello poligonale che potresti avere. Ho anche creato un layer di punti corrispondente che vedrai nell'immagine finale.

inserisci qui la descrizione dell'immagine

Utilizzo delle espressioni

Nota, se si desidera utilizzare una colonna separata, è necessario modificare il secondo argomento in modo che corrisponda al nome della colonna nel set di dati del poligono. Ad esempio, è possibile utilizzare la colonna "AreaNumber", ma dovrebbe corrispondere al tipo di colonna nelle impostazioni della calcolatrice del campo.

inserisci qui la descrizione dell'immagine

Risultato

Puoi vedere che il valore di colonna predefinito è stato applicato in assenza di join spaziali e che gli altri hanno trovato i dati corretti. Nota che lo script che ho dato si unirà solo alla prima partita. Dovresti creare qualche altra logica aziendale se i tuoi poligoni si sovrapponessero.

inserisci qui la descrizione dell'immagine


Molte grazie, la tua sceneggiatura sta funzionando bene usando 'geom' invece di 'geometria' nella prima istruzione 'if'. Unire le geometrie in questo modo può essere molto utile, ad esempio per creare più etichette su poligoni.
Mare lunare,

Scusa, non so come mi sia perso. Spero che non ci siano problemi di prestazioni - l'ho provato solo con un piccolo sottoinsieme di record.
nagytech,

Avere solo più di 100 punti caratterizza QGIS alle prese con problemi di prestazioni. L'aggiunta di una nuova funzione punto è davvero una seccatura anche se non viene visualizzata alcuna funzione punto nella tela acuta. Altrimenti quando si ingrandisce QGIS si accelera. Ho provato "CASE WHEN $ scale <10000 THEN spatialJoinLookupI ('Polygons', 'AreaName', 'None', $ geometry) END 'ma non funziona. C'è qualcosa che posso fare per migliorare le prestazioni?
Lunar Sea

@LunarSea Ho aggiornato la funzione per utilizzare un indice spaziale. Dovrebbe essere ragionevolmente più veloce.
nagytech,

Grazie per l'aiuto. L'unione spaziale ora è molto più veloce ma sfortunatamente qualcosa non funziona correttamente. Sto ottenendo risultati diversi per i punti all'interno dello stesso poligono.
Mare lunare,

8

Può essere fatto in Field Calculator con la funzione aggregate(). Nel livello punto creare un nuovo campo con un'espressione calcolatrice di campo come questa:

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

Dove il layernome del layer poligonale è scritto come una stringa, aggreagateè una funzione aggregata (può essere utilizzata anche come somma ecc.), Il expressioncampo viene prelevato dai valori, concatenatorsi unisce la stringa di caratteri (deve essere impostata, anche in questo caso) e filtersi basa sul filtraggio delle funzionalità sull'espressione (in questo caso intercetta la geometria del livello con la geometria del livello principale).

Per ulteriori informazioni, consultare la documentazione relativa agli aggregati QGIS .

Per gli aggiornamenti automatici è possibile utilizzare i campi virtuali oppure è possibile impostare l'espressione come Valore predefinito nelle Impostazioni modulo attributi in Proprietà livello ( Documentazione impostazione modulo attributi ).

inserisci qui la descrizione dell'immagine


3
Va notato che le funzioni spaziali (con geometry(@parent)) sono supportate solo da QGIS 3 in poi. Nel caso in cui chiunque stia leggendo questo stia ancora usando 2.18 ...
she_weeds

Grazie. Funziona come un fascino.
pensieri spaziali
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.