フィールド計算機の「内」を使用して、ポリゴンレイヤーから属性を選択し、ポイントレイヤーの仮想フィールドに値を挿入する方法はありますか?
CASE
WHEN within($geometry, geometry_polygon) THEN attribute_polygon
END
フィールド計算機の「内」を使用して、ポリゴンレイヤーから属性を選択し、ポイントレイヤーの仮想フィールドに値を挿入する方法はありますか?
CASE
WHEN within($geometry, geometry_polygon) THEN attribute_polygon
END
回答:
デフォルトでは、フィールド計算機はフィーチャレイヤー全体の空間結合をサポートしていません。しかし、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
以下は、使用する可能性のあるポリゴンレイヤーの例です。また、最終画像に表示される対応するポイントレイヤーも作成しました。
別の列を使用する場合は、2番目の引数を変更して、ポリゴンデータセットの列名と一致させる必要があります。たとえば、「AreaNumber」列を使用できますが、フィールド計算機設定の列タイプと一致する必要があります。
空間結合がない場所にデフォルトの列値が適用され、他の値が正しいデータと一致していることがわかります。指定したスクリプトは、最初の一致でのみ参加することに注意してください。ポリゴンが重なっている場合は、他のビジネスロジックを作成する必要があります。
関数を使用してフィールド計算機で実行できますaggregate()
。ポイントレイヤーで、次のようなフィールド計算式を使用して新しいフィールドを作成します。
aggregate(
layer:= 'polygon_layer_name',
aggregate:='concatenate',
expression:=joining_field_name,
concatenator:=', ',
filter:=intersects($geometry, geometry(@parent))
)
ここで、layer
ポリゴンレイヤ名が文字列のように書かれている、aggreagate
(等合計を使用することもできる)集約関数であり、expression
値からフィールドは、採取されているconcatenator
文字列を結合され(この場合にも、セットでなければならない)とfilter
ベースの機能をフィルタリングされon expression(この場合、レイヤージオメトリと親レイヤーのジオメトリを交差させます)。
詳細については、QGISのドキュメントを集計してください。
自動更新のために使用することができる仮想フィールドをかのようにして式を設定することができますデフォルト値での属性は、フォームの設定レイヤープロパティを(属性フォームの設定マニュアルを参照して)。
geometry(@parent)
)はQGIS 3以降でのみサポートされることに注意してください。これを読んでいる人がまだ2.18を使用している場合に備えて...