Apakah ada cara untuk memilih atribut dari lapisan poligon dan memasukkan nilainya ke dalam bidang virtual lapisan titik menggunakan "dalam" dalam kalkulator bidang?
CASE
WHEN within($geometry, geometry_polygon) THEN attribute_polygon
END
Apakah ada cara untuk memilih atribut dari lapisan poligon dan memasukkan nilainya ke dalam bidang virtual lapisan titik menggunakan "dalam" dalam kalkulator bidang?
CASE
WHEN within($geometry, geometry_polygon) THEN attribute_polygon
END
Jawaban:
Di luar kotak, kalkulator bidang tidak mendukung sambungan spasial di seluruh lapisan fitur. Tetapi, jika Anda melihat tulisan NathanW pada editor fungsi untuk ekspresi qgis, Anda akan dapat melihat bahwa kami dapat membuat skrip interaksi data kami sendiri.
Script berikut akan memungkinkan Anda untuk mengekspresikan apa yang Anda cari. Ia bekerja dengan mengulangi semua fitur pada lapisan poligon dan jika ada gabungan spasial, maka referensi data tabular dari kolom yang ditentukan:
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
Di bawah ini adalah contoh lapisan poligon yang mungkin Anda miliki. Saya juga telah membuat layer titik yang sesuai yang akan Anda lihat di gambar akhir.
Catatan, jika Anda ingin menggunakan kolom terpisah, Anda harus mengubah argumen kedua agar cocok dengan nama kolom dalam dataset poligon. Contoh, Anda bisa menggunakan kolom 'AreaNumber', tetapi harus cocok dengan jenis kolom di pengaturan kalkulator lapangan.
Anda dapat melihat bahwa nilai kolom default telah diterapkan di mana tidak ada gabungan spasial, dan yang lain telah cocok dengan data yang benar. Perhatikan skrip yang saya berikan hanya akan bergabung pada pertandingan pertama . Anda perlu membuat beberapa logika bisnis lain jika poligon Anda tumpang tindih.
Ini dapat dilakukan dalam Field Calculator dengan fungsi aggregate()
. Pada layer titik buat bidang baru dengan ekspresi kalkulator bidang seperti ini:
aggregate(
layer:= 'polygon_layer_name',
aggregate:='concatenate',
expression:=joining_field_name,
concatenator:=', ',
filter:=intersects($geometry, geometry(@parent))
)
Di mana layer
nama lapisan poligon ditulis seperti string, aggreagate
adalah fungsi agregat (dapat digunakan juga jumlah, dll.), expression
Adalah bidang dari nilai yang akan diambil, concatenator
bergabung dengan karakter string (harus diatur, bahkan dalam kasus ini) dan filter
memfilter fitur berdasarkan pada ekspresi (dalam hal ini memotong lapisan geometri dengan geometri lapisan induk).
Untuk info lebih lanjut, periksa dokumentasi Agregat QGIS .
Untuk pembaruan otomatis dapat digunakan bidang virtual atau Anda dapat mengatur ekspresi sebagai nilai Default dalam pengaturan Formulir Atribut di Layer Properties ( Dokumentasi pengaturan formulir atribut ).
geometry(@parent)
) hanya didukung dari QGIS 3 dan seterusnya. Kalau-kalau ada orang yang membaca ini masih menggunakan 2.18 ...