Bagaimana cara merujuk ke lapisan lain dalam kalkulator bidang?

26

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

masukkan deskripsi gambar di sini

Laut Bulan
sumber
1
Mengapa tidak menggunakan plugin 'Alat pengambilan sampel titik' untuk ini?
Jakob
Karena saya memerlukan pembaruan dinamis saat membuat poin baru atau memindahkan poin yang ada.
Laut Bulan
Anda akan lebih baik menulis interaksi ini daripada mengandalkan keluar dari alat kotak.
nagytech
Untungnya saya tidak memiliki pengalaman scripting.
Laut Bulan
@ LunarSea Saya telah menulis contoh di bawah ini untuk Anda ikuti, tetapi Anda mungkin harus menyesuaikannya sesuai dengan kebutuhan Anda.
nagytech

Jawaban:

22

Gabungan spasial tersedia di kalkulator lapangan setelah menginstal plugin refFunctions.

geomwithin(targetLayer,targetField)
Laut Bulan
sumber
Pengaya jauh lebih sederhana daripada menggunakan skrip khusus. Terima kasih!
jpmc26
geomwithin ('targetLayer', 'targetField').
Raja
19

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

Contoh Lapisan Poligon

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.

masukkan deskripsi gambar di sini

Penggunaan Ekspresi

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.

masukkan deskripsi gambar di sini

Hasil

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.

masukkan deskripsi gambar di sini

nagytech
sumber
Terima kasih banyak, skrip Anda berfungsi dengan baik menggunakan 'geom' alih-alih 'geometri' dalam pernyataan 'jika' pertama. Menggabungkan geometri dengan cara ini mungkin cukup berguna misalnya untuk membuat beberapa label pada poligon.
Laut Bulan
Maaf, saya tidak tahu bagaimana saya melewatkannya. Semoga tidak ada masalah kinerja - saya hanya mencobanya dengan subset catatan yang sangat kecil.
nagytech
Memiliki hanya 100 poin fitur QGIS berjuang dengan masalah kinerja. Menambahkan fitur titik baru benar-benar menyakitkan bahkan tidak ada fitur titik yang ditampilkan di kanvas acutal. Sebaliknya saat memperbesar QGIS semakin cepat. Saya sudah mencoba `KASUS KAPAN $ skala <10000 KEMUDIAN spatialJoinLookupI ('Poligon', 'AreaName', 'Tidak Ada', $ geometri) AKHIR 'tetapi tidak berfungsi. Adakah yang bisa saya lakukan untuk meningkatkan kinerja?
Laut Bulan
@ LunarSea Saya telah memperbarui fungsi untuk menggunakan indeks spasial. Seharusnya lebih cepat.
nagytech
Terima kasih atas bantuan Anda. Penggabungan spasial jauh lebih cepat sekarang tetapi sayangnya ada sesuatu yang tidak berfungsi dengan baik. Saya mendapatkan hasil yang berbeda untuk poin dalam satu dan poligon yang sama.
Laut Lunar
8

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 layernama lapisan poligon ditulis seperti string, aggreagateadalah fungsi agregat (dapat digunakan juga jumlah, dll.), expressionAdalah bidang dari nilai yang akan diambil, concatenatorbergabung dengan karakter string (harus diatur, bahkan dalam kasus ini) dan filtermemfilter 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 ).

masukkan deskripsi gambar di sini

Oto Kaláb
sumber
3
Perlu dicatat bahwa fungsi spasial (dengan geometry(@parent)) hanya didukung dari QGIS 3 dan seterusnya. Kalau-kalau ada orang yang membaca ini masih menggunakan 2.18 ...
she_weeds
Terima kasih. Bekerja seperti pesona.
spatialthoughts