如何在现场计算器中引用另一层?


26

有没有一种方法可以从多边形图层中选择属性,然后使用字段计算器中的“内”将值插入点图层的虚拟字段中?

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

在此处输入图片说明


1
为什么不为此使用“点采样工具”插件?
雅各布2015年

因为创建新点或移动现有点时需要动态更新。
农历海

您最好对这种交互进行脚本编写,而不要依靠现成的工具。
nagytech

毫无疑问,我没有任何脚本编写经验。
月球海

@LunarSea我在下面编写了一个示例供您遵循,但是您可能必须对其进行调整以满足您的需求。
nagytech

Answers:


22

安装refFunctions插件后,在空间计算器中可以使用空间连接。

geomwithin(targetLayer,targetField)

插件比使用自定义脚本简单得多。谢谢!
jpmc26

geomwithin('targetLayer','targetField')。
拉贾

19

开箱即用的字段计算器不支持跨要素图层的空间连接。但是,如果您看一下函数编辑器上有关qgis表达式的 NathanW帖子,您将能够发现我们可以编写自己的数据交互脚本。

以下脚本可让您表达所追求的目标。它的工作方式是遍历多边形层上的所有要素,如果存在空间连接,则从指定的列中引用表格数据:

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

多边形层示例

以下是您可能拥有的多边形图层的示例。我还创建了一个相应的点图层,您将在最终图像中看到该图层。

在此处输入图片说明

表达式用法

注意,如果要使用单独的列,则必须更改第二个参数以匹配面数据集中的列名。例如,您可以使用“ AreaNumber”列,但必须与字段计算器设置中的列类型匹配。

在此处输入图片说明

结果

您会看到默认列值已应用到没有空间连接的地方,而另一个已匹配正确的数据。请注意,我提供的脚本只会在第一个比赛中加入。如果多边形重叠,则需要创建其他业务逻辑。

在此处输入图片说明


非常感谢,您的脚本在第一个“ if”语句中使用“ geom”而不是“ geometry”可以正常工作。这种方式连接几何图形可能非常有用,例如,在多边形上创建多个标签。
农历海

抱歉,我不知道我怎么想的。希望没有性能问题-我只用了很小的一部分记录就尝试了。
nagytech

只有100多个点要素,QGIS一直在解决性能问题。即使在原始画布中没有显示任何点要素,添加新的点要素也确实很痛苦。否则,放大QGIS时会加快速度。我尝试了`$ scale <10000 THEN spaceJoinLookupI('Polygons','AreaName','None',$ geometry)END'的情况,但是它不起作用。我有什么办法可以改善性能?
月球海

@LunarSea我已经更新了功能以使用空间索引。它应该合理地更快。
nagytech

谢谢你的帮助。现在,空间连接的速度要快得多,但不幸的是某些操作无法正常进行。对于同一多边形内的点,我得到的结果不同。
月球海

8

可以在具有功能的Field Calculator中完成aggregate()。在点层中,使用字段计算器表达式创建新字段,如下所示:

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

其中layer被多边形层名字写像字符串,aggreagate是聚集函数(可使用也总结等),expression是从值字段将被采取,concatenator被接合的字符串(必须设定,即使在这种情况下)和filter被滤波基于特征on表达式(在这种情况下,层几何与父层几何相交)。

有关更多信息,请查看“ 聚合QGIS文档”

对于自动更新,可以使用虚拟字段,也可以在“ 图层属性”(“ 属性表单设置文档”)中的“ 属性表单”设置中将表达式设置为“ 默认值”

在此处输入图片说明


2
应该注意的是,geometry(@parent)仅从QGIS 3开始支持空间功能(带有)。以防万一有人阅读本文仍在使用2.18 ...
she_weeds

谢谢。奇迹般有效。
spacethoughts
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.