จะตรวจสอบรหัสกระเบื้องใกล้เคียงใน QGIS ได้อย่างไร?


11

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

แต่จากนั้นเราก็เริ่มนึกถึงตัวอย่างที่เป็นจริงที่เราไม่ต้องการวาดหน้าเว็บที่ไม่มีเขตที่เราสนใจเช่นหนึ่งในเขตของฉัน:

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

ดังนั้นบ่ายนี้ฉันได้เล่นสคริปต์ไพ ธ อนเพื่อหา 4 เพื่อนบ้านที่ฉันสนใจสำหรับแต่ละตารางเซลล์และเพิ่มค่าเหล่านั้นในตารางของฉัน (นี่ขึ้นอยู่กับการสอนของ Ujaval Gandhi )

for f in feature_dict.values():
    print 'Working on %s' % f[_NAME_FIELD]
    geom = f.geometry()
    # Find all features that intersect the bounding box of the current feature.
    # We use spatial index to find the features intersecting the bounding box
    # of the current feature. This will narrow down the features that we need
    # to check neighboring features.
    intersecting_ids = index.intersects(geom.boundingBox())
    # Initalize neighbors list and sum
    neighbors = []
    neighbors_sum = 0
    for intersecting_id in intersecting_ids:
        # Look up the feature from the dictionary
        intersecting_f = feature_dict[intersecting_id]
        int_geom = intersecting_f.geometry()
        centroid = geom.centroid()
        height = geom.boundingBox().height()
        width = geom.boundingBox().width()
        # For our purpose we consider a feature as 'neighbor' if it touches or
        # intersects a feature. We use the 'disjoint' predicate to satisfy
        # these conditions. So if a feature is not disjoint, it is a neighbor.
        if (f != intersecting_f and
            not int_geom.disjoint(geom)):
            above_point = QgsGeometry.fromPoint(QgsPoint(centroid.asPoint().x(),
               centroid.asPoint().y()+height))
            below_point = QgsGeometry.fromPoint(QgsPoint(centroid.asPoint().x(),
               centroid.asPoint().y()-height))
            left_point = QgsGeometry.fromPoint(QgsPoint(centroid.asPoint().x()-width,
               centroid.asPoint().y()))
            right_point = QgsGeometry.fromPoint(QgsPoint(centroid.asPoint().x()+width,
               centroid.asPoint().y()))
            above = int_geom.contains(above_point)   
            below = int_geom.contains(below_point)   
            left = int_geom.contains(left_point)
            right = int_geom.contains(right_point)
            if above:
                print "setting %d as above %d"%(intersecting_f['id'],f['id'])
                f['above']=intersecting_f['id']

            if below:
                print "setting %d as below %d"%(intersecting_f['id'],f['id'])
                f['below']=intersecting_f['id']

            if left:
                print "setting %d as left of %d"%(intersecting_f['id'],f['id'])
                f['left']=intersecting_f['id']

            if right:
                print "setting %d as right of %d"%(intersecting_f['id'],f['id'])
                f['right']=intersecting_f['id']

    # Update the layer with new attribute values.
    layer.updateFeature(f)

layer.commitChanges()

มันใช้งานได้ดี

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

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

เป็นการดีที่ฉันต้องการสิ่งที่ง่ายพอที่จะใส่ในกล่องข้อความผู้แต่งเพลงพิมพ์ แต่ฉันคิดว่ามันเกินกว่าจะขอได้


เกิดอะไรขึ้นถ้าไม่มีเพื่อนบ้านอยู่ด้านหนึ่ง คุณต้องการคุณค่าของเซลล์ closeset ในทิศทางเดียวหรือคุณจะปล่อยให้เป็นโมฆะ?
radouxju

ฉันมีความสุขกับการเป็นโมฆะในกรณีนี้ฉันสามารถตั้งค่าป้ายกำกับให้แสดงเฉพาะเมื่อไม่เป็นโมฆะหรือว่างเปล่า
Ian Turton

คำตอบ:


3

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

หากไม่มีการซ้อนทับกันคุณสามารถทำซ้ำเทคนิคที่ฉันใช้ประสบความสำเร็จในอดีต (บังเอิญข้าม E & W Sussex!) ใน MapInfo ที่ฉันเขียนสคริปต์ขนาดเล็กที่สร้างชุดของสี่จุดสำหรับแต่ละดัชนีคุณลักษณะ ชดเชยในคุณสมบัติที่อยู่ติดกันที่มีคุณสมบัติของทั้งหมายเลขแผ่นและทิศทางของการชดเชย เลเยอร์จุดนั้นถูกใช้เพื่อสร้างฉลากอีกครั้งโดยมีทิศทางของออฟเซ็ตทำให้สามารถปรับทิศทางของฉลากเพื่อให้ได้ผลที่ดีกว่า

ฉันไม่ได้ลองสิ่งนี้ แต่คุณสามารถหลีกเลี่ยงการสร้างเลเยอร์ข้อมูลแยกต่างหากใน QGIS ผ่านการใช้ฟังก์ชันการทำงานของตัวสร้างรูปทรงเรขาคณิตตัวใหม่ซึ่งจะทำให้โซลูชันที่หรูหราและมีชีวิตชีวาที่ไม่สามารถทำได้ใน MapInfo!


ฉันควรนึกถึงการใช้ป้ายกำกับของรูปหลายเหลี่ยมอื่น ๆ ! :-) หลังจากการทดสอบอย่างรวดเร็วด้วยเครื่องสร้างรูปทรงเรขาคณิตฉันสามารถวาดกล่องล้อมรอบ แต่มันยากที่จะสร้างตาราง
Ian Turton

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

เพิ่งมีการเล่นและปรากฏว่ารูปทรงเรขาคณิตที่สร้างโดยตัวสร้างรูปทรงเรขาคณิตนั้นไม่ได้รับการติดฉลากดังนั้นจึงไม่ใช่คำตอบที่สวยงามยิ่งกว่าที่ฉันหวังไว้
Andy Harfoot

8

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

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

ก่อนอื่นเราต้องแสดงฉลากของแต่ละกริด

ในมุมมองเค้าโครงฉันใช้กริดเป็นเลเยอร์พื้นที่ครอบคลุมในแอตลาสฉันสร้างแผนที่สองแผนที่แผนที่หน้าต่างมุมมองหลักและแผนที่ดัชนีที่แสดงเฉพาะตารางดังที่คุณเห็นด้านล่าง:

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

จากนั้นฉันก็ทำสิ่งต่อไปนี้:

  1. ฉันปรับสเกลของแผนที่ดัชนีเพื่อแสดงขอบเขตกริดทั้งหมดจากนั้นฉันแก้ไขสเกล
  2. ฉันแก้ไขขอบเขตการดูเพื่อป้องกันไม่ให้แผนที่ปรากฎเมื่อใช้ Preview atlasและ
  3. ฉันเปิดใช้งานOverviewเพื่อดูขอบเขตและตำแหน่งของแผนที่มุมมองหลักตามที่คุณเห็นด้านล่าง:

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

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

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

ใช้แผนที่ดัชนีคุณสามารถดู ID และที่ตั้งของแต่ละไทล์ได้อย่างง่ายดายโดยอ้างอิงกับไทล์อื่น ๆ แม้ว่าคุณจะปิดตารางจากหน้าต่างแผนที่มุมมองหลัก ตัวอย่างเช่นแผนที่ต่อไปนี้มีไทล์ ID = 14 และคุณสามารถดูไทล์ ID ที่ล้อมรอบ

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

อัปเดต :

ฉันจะอัปเดตคำตอบของฉันเพราะฉันรู้ว่าคุณต้องการแสดงดัชนีหมายเลขหน้าของเค้าโครงโดยรอบไม่ใช่ ID ของโครงร่างโดยรอบ

เพื่อความเข้าใจที่ง่ายขึ้นของกระบวนการฉันจะอัปเดตหมายเลข ID ในแผนที่ดัชนีเพื่อแสดงหมายเลขหน้าเลย์เอาต์ดังที่แสดงด้านล่าง:

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

เนื่องจาก ID ที่ฉันเริ่มต้นจาก 0 (ศูนย์), ID ของกริดแรกที่แสดงบนแผนที่ดัชนีจะเริ่มจาก 3 ดังนั้นฉันต้องการเปลี่ยนหมายเลขหน้าให้เริ่มจาก 1 โดยลบ 2 จากหมายเลข ID ใน Atlas: Page number: ID -2จากนั้นฉันจะใช้หมายเลขหน้าปัจจุบันเป็นข้อมูลอ้างอิงในนิพจน์เพื่อสร้างป้ายกำกับสำหรับหน้าปัจจุบันหน้าก่อนหน้าหน้าถัดไปหน้าขึ้นและหน้าล่างดังต่อไปนี้:

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

  • หน้าปัจจุบันมีนิพจน์นี้ในกล่องข้อความป้ายกำกับ: Current Page Number: [%@atlas_pagename%]

  • นิพจน์หน้าก่อนหน้า: [%if((@atlas_pagename = 1), Null, '↑ Page Number: ' || (@atlas_pagename - 1))%]เนื่องจากไม่มีหน้าก่อน 1

  • นิพจน์หน้าถัดไป: [%if( (@atlas_pagename = 25), Null, '↓ Page Number: ' || (@atlas_pagename + 1))%]เนื่องจากไม่มีหน้าหลังจาก 25

  • นิพจน์หน้าขึ้น: [%if((@atlas_pagename <= 6),NULL,'↑ Page Number: ' || (@atlas_pagename -6))%]เนื่องจากไม่มีหน้าก่อนหน้า 6 ในทิศทางบน

  • ด้านล่างนิพจน์หน้า: [%if((@atlas_pagename >= 20), Null, '↓ Page Number: ' || (@atlas_pagename + 6))%]เนื่องจากไม่มีหน้าหลังจาก 20 ในทิศทางที่ต่ำกว่า

ผลลัพธ์บางส่วน:

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

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

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

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


แม้ว่าจะมีประโยชน์ แต่นี่ไม่ได้ตอบคำถามของเขา
วิกเตอร์

@Victor ขอบคุณสำหรับความคิดเห็นของคุณฉันได้อัพเดตคำตอบแล้ว
ahmadhanb

สิ่งนี้ใช้ได้ในตัวอย่างของคุณ (และของเขา) เนื่องจากด้านข้างของ keymap / grid เป็นแบบปกติ หากพวกเขาไม่ตรงมันจะไม่ทำงานเนื่องจากจำนวนที่จะเพิ่มหรือลบ (6 ในตัวอย่างของคุณ) จะแตกต่างกันไปขึ้นอยู่กับหน้าแอตลาสที่คุณอยู่
Victor

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

เพียงสังเกตความจริงในกรณีที่คุณมีความคิดที่ดีอีก! โดยเฉพาะอย่างยิ่งเนื่องจากตารางของฉันไม่ปกติ!
วิกเตอร์

2

โซลูชันนี้จะทำงานสำหรับกริดสี่เหลี่ยมและเป็นไปโดยอัตโนมัติ (ควรทำงานกับสถานการณ์ใด ๆ โดยไม่ต้องปรับอะไรด้วยตนเอง)

สมมติว่าคุณมีตารางที่มีหมายเลขหน้า คุณสามารถรันสคริปต์ประมวลผลของฉันโดยเลือกเลเยอร์กริดและฟิลด์หมายเลขหน้าเป็นพารามิเตอร์ สคริปต์สร้างสี่ฟิลด์ ( right, left, above, below) ในชั้นตารางและคำนวณ id หน้าเพื่อนบ้านที่เกี่ยวข้องสำหรับแต่ละตารางเซลล์ จากนั้นคุณสามารถใช้นิพจน์ของคุณ (เช่น[% if( "left" is not NULL, 'to page' || "left", "" ) %]) เพื่อแสดงป้ายกำกับหน้าเพื่อนบ้าน

เพียงเพิ่มที่เก็บของฉัน ( https://github.com/gacarrillor/QGIS-Resources.git ) จากปลั๊กอินการแชร์ทรัพยากร QGIS และติดตั้งสคริปต์: ป้อนคำอธิบายรูปภาพที่นี่

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

มันทำงานอย่างไร

สคริปต์จะกำหนดความสัมพันธ์ (ขวา, ซ้าย, ด้านบนหรือด้านล่าง) โดยการเปรียบเทียบพิกัดกล่องขอบเขตจากทั้งกริดเซลล์ปัจจุบันและเซลล์ที่ตัดกันแต่ละเซลล์ ปรากฎว่าสำหรับแต่ละความสัมพันธ์หนึ่งในพิกัดหายไป

หากความสัมพันธ์คือaboveพิกัดที่ขาดหายไปคือพิกัดyMin3 อื่น ๆ ทั้งหมดจากกล่อง จำกัด ของเซลล์กริดปัจจุบันจะปรากฏในกล่องขอบของเซลล์ด้านบน โปรดจำไว้ว่า QGIS bounding [xMin, yMin, xMax, yMax]กล่องที่กำหนดไว้ในคำสั่งนี้:

สำหรับตัวอย่างที่ปล่อยให้เป็นตัวเลขใช้เวลาสี่เหลี่ยมที่มีด้านของความยาว 1. Say bbox1=[0,0,1,1]กล่องขอบเขตเซลล์ปัจจุบันถูกกำหนดให้เป็น bbox2=[0,1,1,2]ช่องขอบเซลล์ดังกล่าวข้างต้นจะถูกกำหนดเป็น พิกัด X จาก bbox1 มีอยู่ใน bbox2 ในขณะที่ bbox1 yMinขาดหายไปในพิกัด Y ของ bbox2

เราสามารถกำหนดความสัมพันธ์ 4 รายการของเราด้วยวิธีนี้ (o: ปัจจุบัน, #: หายไป):

right: [#,o,o,o]
above: [o,#,o,o]
left:  [o,o,#,o]
below: [o,o,o,#]

อย่างที่คุณเห็นดัชนีที่หายไปให้ข้อมูลทั้งหมดที่เราต้องการ

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