¿Cómo hacer referencia a otra capa en la calculadora de campo?

26

¿Hay alguna manera de seleccionar un atributo de una capa de polígono e insertar el valor en un campo virtual de una capa de puntos usando "dentro" en la calculadora de campo?

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

ingrese la descripción de la imagen aquí

Mar lunar
fuente
1
¿Por qué no utilizar el complemento 'Herramienta de muestreo de puntos' para esto?
Jakob
Porque necesito actualizaciones dinámicas al crear nuevos puntos o mover puntos existentes.
Mar Lunar
Sería mejor crear scripts para esta interacción en lugar de confiar en herramientas listas para usar.
nagytech
Desafortunadamente, no tengo ninguna experiencia en secuencias de comandos.
Mar Lunar
@LunarSea He escrito un ejemplo a continuación para que lo sigas, pero es posible que tengas que ajustarlo para satisfacer tus necesidades.
nagytech

Respuestas:

22

Las uniones espaciales están disponibles en la calculadora de campo después de instalar el complemento refFunctions.

geomwithin(targetLayer,targetField)
Mar lunar
fuente
Los complementos son mucho más simples que usar un script personalizado. ¡Gracias!
jpmc26
geomwithin ('targetLayer', 'targetField').
Raja
19

Fuera de la caja, la calculadora de campo no admite uniones espaciales a través de capas de entidades. Pero, si echa un vistazo a la publicación de NathanW en el editor de funciones para expresiones qgis , podrá ver que podemos escribir nuestra propia interacción de datos.

El siguiente script le permitirá expresar lo que busca. Funciona iterando a través de todas las entidades en la capa de polígono y si hay una unión espacial, entonces haga referencia a los datos tabulares de la columna 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

Ejemplo de capa de polígono

A continuación se muestra un ejemplo de una capa de polígono que podría tener. También he creado una capa de puntos correspondiente que verá en la imagen final.

ingrese la descripción de la imagen aquí

Uso de expresiones

Tenga en cuenta que si desea utilizar una columna separada, debe cambiar el segundo argumento para que coincida con el nombre de la columna en el conjunto de datos del polígono. Por ejemplo, podría usar la columna 'ÁreaNúmero', pero tendría que coincidir con el tipo de columna en la configuración de la calculadora de campo.

ingrese la descripción de la imagen aquí

Resultado

Puede ver que el valor de columna predeterminado se ha aplicado donde no hay unión espacial, y los otros han coincidido con los datos correctos. Tenga en cuenta que el script que he dado solo se unirá en la primera coincidencia. Debería crear alguna otra lógica de negocios si sus polígonos se superpusieran.

ingrese la descripción de la imagen aquí

nagytech
fuente
Muchas gracias, su script está funcionando bien usando 'geom' en lugar de 'geometry' en la primera declaración 'if'. Unir geometrías de esta manera puede ser bastante útil, por ejemplo, para crear múltiples etiquetas en polígonos.
Mar Lunar
Lo siento, no sé cómo me perdí eso. Esperemos que no haya problemas de rendimiento: solo lo probé con un subconjunto muy pequeño de registros.
nagytech
Con solo más de 100 puntos de características, QGIS lucha con problemas de rendimiento. Agregar una nueva característica de punto es realmente un dolor, incluso si no se muestra ninguna característica de punto en el lienzo acutal. De lo contrario, al hacer zoom en QGIS se acelera. Intenté `CASE WHEN $ scale <10000 THEN spatialJoinLookupI ('Polygons', 'AreaName', 'None', $ geometry) END 'pero no funciona. ¿Hay algo que pueda hacer para mejorar el rendimiento?
Mar Lunar
@LunarSea He actualizado la función para usar un índice espacial. Debería ser razonablemente más rápido.
nagytech
Gracias por tu ayuda. La unión espacial es mucho más rápida ahora, pero desafortunadamente algo no funciona correctamente. Estoy obteniendo resultados diferentes para puntos dentro del mismo polígono.
Mar Lunar
8

Se puede hacer en Field Calculator con función aggregate(). En la capa de puntos, cree un nuevo campo con una expresión de calculadora de campo como esta:

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

Donde el layernombre de la capa de polígono se escribe como una cadena, aggreagatees una función de agregado (se puede usar también suma, etc.), expressionse tomará el campo de los valores, concatenatorse une a la cadena de caracteres (debe establecerse, incluso en este caso) y filterse basa en el filtrado de características en expresión (en este caso interesa la geometría de la capa con la geometría de la capa primaria).

Para obtener más información de verificación de documentación Agregados QGIS .

Para las actualizaciones automáticas se pueden usar campos virtuales o puede establecer la expresión como valor predeterminado en la configuración del formulario de atributos en Propiedades de capa ( documentación de configuración del formulario de atributos ).

ingrese la descripción de la imagen aquí

Oto Kaláb
fuente
3
Cabe señalar que las funciones espaciales (con geometry(@parent)) solo son compatibles desde QGIS 3 en adelante. Por si alguien que lee esto todavía usa 2.18 ...
she_weeds
Gracias. Funciona de maravilla.
pensamientos espaciales