Como se referir a outra camada na calculadora de campo?

26

Existe uma maneira de selecionar um atributo de uma camada de polígono e inserir o valor no campo virtual de uma camada de pontos usando "dentro" na calculadora de campos?

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

insira a descrição da imagem aqui

Mar Lunar
fonte
11
Por que não usar o plugin 'Point sampling tool' para isso?
27415 Jakob
Porque preciso de atualizações dinâmicas ao criar novos pontos ou mover pontos existentes.
Sea Lunar
Seria melhor criar scripts para essa interação do que confiar nas ferramentas prontas para uso.
Nagytech 28/06
Infelizmente, não tenho nenhuma experiência com scripts.
Sea Lunar
@LunarSea Escrevi um exemplo abaixo para você seguir, mas você pode precisar ajustá-lo para atender às suas necessidades.
Nagytech

Respostas:

22

Junções espaciais estão disponíveis na calculadora de campo após a instalação do plug-in refFunctions.

geomwithin(targetLayer,targetField)
Mar Lunar
fonte
Os plug-ins são muito mais simples do que usar um script personalizado. Obrigado!
precisa saber é
geomwithin ('targetLayer', 'targetField').
Raja
19

Fora da caixa, a calculadora de campo não suporta junções espaciais nas camadas de recurso. Mas, se você der uma olhada na postagem de NathanW no editor de funções para expressões qgis, poderá concluir que podemos criar um script para nossa própria interação de dados.

O script a seguir permitirá que você expresse o que procura. Ele funciona iterando todos os recursos da camada de polígono e, se houver uma junção espacial, faça referência aos dados tabulares da coluna especificada:

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

Exemplo de camada de polígono

Abaixo está um exemplo de uma camada de polígono que você pode ter. Também criei uma camada de pontos correspondente que você verá na imagem final.

insira a descrição da imagem aqui

Uso da expressão

Observe que, se você quiser usar uma coluna separada, altere o segundo argumento para corresponder ao nome da coluna no conjunto de dados do polígono. Por exemplo, você poderia usar a coluna 'AreaNumber', mas precisaria corresponder ao tipo da coluna nas configurações da calculadora de campo.

insira a descrição da imagem aqui

Resultado

Você pode ver que o valor padrão da coluna foi aplicado onde não há junção espacial e os outros corresponderam aos dados corretos. Observe que o script que eu forneci entrará apenas na primeira partida. Você precisaria criar alguma outra lógica comercial se seus polígonos estivessem sobrepostos.

insira a descrição da imagem aqui

nagytech
fonte
Muito obrigado, seu script está funcionando bem usando 'geom' em vez de 'geometry' na primeira instrução 'if'. Unir geometrias dessa maneira pode ser bastante útil, por exemplo, para criar várias etiquetas em polígonos.
Sea Lunar
Desculpe, não sei como senti falta disso. Espero que não haja problemas de desempenho - tentei apenas com um subconjunto muito pequeno de registros.
Nagytech 29/06
Tendo apenas mais de 100 pontos, o QGIS enfrenta problemas de desempenho. Adicionar um novo recurso de ponto é realmente uma dor, mesmo que não haja nenhum recurso de ponto exibido na tela acutal. Caso contrário, ao aumentar o zoom, o QGIS acelera. Tentei `CASE WHEN $ scale <10000 THEN spatialJoinLookupI ('Polygons', 'AreaName', 'None', $ geometry) END ', mas não está funcionando. Existe algo que eu possa fazer para melhorar o desempenho?
Mar Lunar
@LunarSea Atualizei a função para usar um índice espacial. Deve ser razoavelmente mais rápido.
Nagytech
Obrigado pela ajuda. A junção espacial é muito mais rápida agora, mas infelizmente algo não está funcionando corretamente. Estou obtendo resultados diferentes para pontos dentro de um e o mesmo polígono.
Mar Lunar
8

Isso pode ser feito em Calculator campo com a função aggregate(). Na camada de ponto, crie um novo campo com a expressão da calculadora de campo como esta:

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

Onde o layernome da camada de polígono é escrito como string, aggreagateé a função agregada (pode ser usada também como soma etc.), o expressioncampo a partir dos valores será obtido, a concatenatorjunção da cadeia de caracteres (deve ser definida, mesmo nesse caso) e a filterfiltragem de recursos com base na expressão (neste caso, intercepta a geometria da camada com a geometria da camada pai).

Para mais informações, consulte Agregar a documentação do QGIS .

Para atualizações automáticas, podem ser usados campos virtuais ou você pode definir a expressão como Valor padrão nas configurações de Formulário de atributos em Propriedades da camada ( documentação de configuração de formulário de atributo ).

insira a descrição da imagem aqui

Oto Kaláb
fonte
3
Note-se que as funções espaciais (com geometry(@parent)) são suportadas apenas a partir do QGIS 3. Caso alguém que esteja lendo isso ainda esteja usando 2,18 ...
she_weeds 24/03
Obrigado. Funciona como um encanto.
spatialthoughts