จะอ้างถึงเลเยอร์อื่นในตัวคำนวณฟิลด์ได้อย่างไร


26

มีวิธีการเลือกแอตทริบิวต์จากรูปหลายเหลี่ยมเลเยอร์และแทรกค่าลงในเขตข้อมูลเสมือนของชั้นจุดโดยใช้ "ภายใน" ในเครื่องคิดเลขฟิลด์หรือไม่?

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

ป้อนคำอธิบายรูปภาพที่นี่


1
ทำไมไม่ใช้ปลั๊กอิน 'เครื่องมือสุ่มตัวอย่าง' สำหรับสิ่งนี้
Jakob

เพราะฉันต้องการการปรับปรุงแบบไดนามิกเมื่อสร้างจุดใหม่หรือย้ายจุดที่มีอยู่
Sea Lunar

คุณจะดีกว่าการเขียนสคริปต์การโต้ตอบนี้แทนที่จะพึ่งพาเครื่องมือกล่อง
nagytech

ฉันไม่ได้มีประสบการณ์การเขียนสคริปต์เลย
Sea Lunar

@ LunarSea ฉันได้เขียนตัวอย่างด้านล่างเพื่อให้คุณติดตาม แต่คุณอาจต้องปรับแต่งมันเพื่อให้เหมาะกับความต้องการของคุณ
nagytech

คำตอบ:


22

การรวมเชิงพื้นที่มีอยู่ในเครื่องคิดเลขภาคสนามหลังจากติดตั้งปลั๊กอิน refFunctions

geomwithin(targetLayer,targetField)

ปลั๊กอินนั้นง่ายกว่าการใช้สคริปต์ที่กำหนดเอง ขอบคุณ!
jpmc26

geomwithin ( 'targetLayer', 'targetField')
ราชา

19

เครื่องคิดเลขภาคสนามไม่รองรับการรวมเชิงพื้นที่ในเลเยอร์คุณลักษณะ แต่ถ้าคุณดูที่โพสต์ของ NathanW ในตัวแก้ไขฟังก์ชั่นสำหรับการแสดงออก qgisคุณจะสามารถระบุได้ว่าเราสามารถเขียนสคริปต์การโต้ตอบข้อมูลของเราเอง

สคริปต์ต่อไปนี้จะช่วยให้คุณแสดงสิ่งที่คุณต้องการ มันทำงานได้โดยการวนซ้ำผ่านฟีเจอร์ทั้งหมดบนเลเยอร์รูปหลายเหลี่ยมและหากมีการรวมเชิงพื้นที่ให้อ้างอิงข้อมูลตารางจากคอลัมน์ที่ระบุ:

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' แต่จะต้องตรงกับประเภทคอลัมน์ในการตั้งค่าเครื่องคิดเลข

ป้อนคำอธิบายรูปภาพที่นี่

ผล

คุณจะเห็นว่ามีการใช้ค่าคอลัมน์เริ่มต้นในกรณีที่ไม่มีการรวมเชิงพื้นที่และอีกรายการหนึ่งจับคู่ข้อมูลที่ถูกต้อง โปรดทราบว่าสคริปต์ที่ฉันให้จะเข้าร่วมในนัดแรกเท่านั้น คุณจะต้องสร้างตรรกะทางธุรกิจอื่น ๆ หากรูปหลายเหลี่ยมของคุณทับซ้อนกัน

ป้อนคำอธิบายรูปภาพที่นี่


ขอบคุณมากสคริปต์ของคุณทำงานได้ดีโดยใช้ 'geom' แทน 'geometry' ในคำสั่ง 'if' การเข้าร่วมรูปทรงเรขาคณิตด้วยวิธีนี้อาจมีประโยชน์มากเช่นการสร้างป้ายกำกับหลายป้ายบนรูปหลายเหลี่ยม
Lunar Sea

ขออภัยฉันไม่ทราบว่าฉันพลาดได้อย่างไร หวังว่าจะไม่มีปัญหาด้านประสิทธิภาพ - ฉันลองใช้ชุดข้อมูลเพียงเล็กน้อยเท่านั้น
nagytech

การมีฟีเจอร์ 100+ point ที่ QGIS ต่อสู้กับปัญหาด้านประสิทธิภาพ การเพิ่มฟีเจอร์จุดใหม่นั้นเป็นเรื่องที่เจ็บปวดจริงๆแม้ว่าจะไม่มีฟีเจอร์จุดใดที่แสดงบนแคนวาส มิฉะนั้นเมื่อซูมด้วย QGIS จะมีความเร็วสูงขึ้น ฉันได้ลองใช้ 'กรณีเมื่อ $ scale <10,000 แล้ว spatialJoinLookupI (' รูปหลายเหลี่ยม ',' AreaName ',' None ', $ geometry) END' แต่มันไม่ทำงาน มีอะไรที่ฉันสามารถทำได้เพื่อปรับปรุงประสิทธิภาพหรือไม่
Lunar Sea

@ LunarSea ฉันได้อัพเดทฟังก์ชั่นการใช้ดัชนีอวกาศ มันควรจะเร็วกว่าพอสมควร
nagytech

ขอบคุณสำหรับความช่วยเหลือของคุณ. การเข้าร่วมเชิงพื้นที่เร็วขึ้นมากในขณะนี้ แต่บางสิ่งบางอย่างไม่ได้ผล ฉันได้ผลลัพธ์ที่ต่างกันสำหรับจุดต่าง ๆ ภายในหนึ่งและรูปหลายเหลี่ยมเดียวกัน
Lunar Sea

8

ก็สามารถทำได้ในการคำนวณสนามaggregate()ที่มีฟังก์ชั่น ในเลเยอร์พอยต์สร้างฟิลด์ใหม่ด้วยนิพจน์ฟิลด์เครื่องคิดเลขดังนี้:

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

โดยที่layerชื่อเลเยอร์รูปหลายเหลี่ยมที่เขียนเหมือนสตริงaggreagateคือฟังก์ชันรวม (สามารถใช้รวมได้เช่นกัน) expressionคือฟิลด์จากค่าที่จะถูกนำมาconcatenatorเข้าร่วมสตริงอักขระ (ต้องตั้งค่าแม้ในกรณีนี้) และfilterเป็นคุณสมบัติการกรองตาม ในการแสดงออก (ในกรณีนี้ interesects เรขาคณิตชั้นกับเรขาคณิตของผู้ปกครองชั้น)

สำหรับข้อมูลเพิ่มเติมตรวจสอบเอกสาร Aggregates QGIS

สำหรับการอัปเดตอัตโนมัติสามารถใช้ฟิลด์เสมือนหรือคุณสามารถตั้งค่านิพจน์เป็นค่าเริ่มต้นในการตั้งค่าแบบฟอร์มคุณสมบัติในคุณสมบัติเลเยอร์ ( เอกสารการตั้งค่ารูปแบบคุณสมบัติ )

ป้อนคำอธิบายรูปภาพที่นี่


2
ควรสังเกตว่าฟังก์ชั่นเชิงพื้นที่ (พร้อมgeometry(@parent)) ได้รับการสนับสนุนจาก QGIS 3 เป็นต้นไป ในกรณีที่ทุกคนที่อ่านข้อความนี้ยังคงใช้ 2.18 ...
she_weeds

ขอขอบคุณ. ทำงานเหมือนจับใจ
คิดเชิงพื้นที่
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.