ใส่สไตล์เลเยอร์เฉพาะโดยใช้หน้ากากหลายเหลี่ยมใน QGIS?


10

ฉันมีเลเยอร์บรรทัดและเลเยอร์หลายเหลี่ยมใน QGIS:

ก่อนที่จะมาส์ก

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

หลังจากพอกหน้า

ฉันไม่ต้องการสร้างชุดข้อมูลอนุพันธ์เช่น คลิปเลเยอร์บรรทัดและลักษณะสองส่วน

นี่เป็นกรณีที่เรียบง่าย แต่ในโครงการ QGIS ของฉันฉันมีเลเยอร์ 30 ชั้นดังนั้นฉันคิดว่าการผสมเลเยอร์ใด ๆ จะรบกวนเลเยอร์พื้นฐาน

เป็นไปได้ไหมที่จะทำอะไรแบบนี้?

ฉันไม่ต้องการแสดงเลเยอร์รูปหลายเหลี่ยมมันเป็นเพียงที่นี่เพื่อให้เห็นภาพสิ่งที่ฉันต้องการจะทำ


1
เป็นวิธีที่ดี! ผมคิดว่าควรจะโพสต์เป็นคำตอบแทนการแก้ไขเพื่อคำถาม :)
โจเซฟ

@ โจเซฟเสร็จแล้ว!
Chau

คำตอบ:


11

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

เพิ่มเลเยอร์สัญลักษณ์ใหม่โดยคลิกที่เครื่องหมายบวกและเลือกGeometry generatorประเภทเลเยอร์สัญลักษณ์ ตั้งค่าประเภท geoemtry เป็นLineString / MultiLineStringและใช้นิพจน์ต่อไปนี้:

intersection($geometry, geometry(get_feature( 'polygonLayer','fieldName','value'))) 

คุณจะต้องเพิ่มรายละเอียดเกี่ยวกับรูปหลายเหลี่ยมเฉพาะที่:

  • polygonLayer เป็นชื่อของเลเยอร์รูปหลายเหลี่ยมของคุณ
  • fieldName เป็นชื่อของฟิลด์
  • value คือค่าคุณสมบัติของรูปหลายเหลี่ยมเฉพาะของคุณ

คุณสมบัติของสไตล์

โปรดทราบว่าหากต้องการระบายสีเส้นภาพคุณอาจต้องทำจากคุณสมบัติเอฟเฟ็กต์วาด :

วาดคุณสมบัติผลกระทบ

นี่เป็นผลลัพธ์ (โปรดสังเกตว่าเส้นภาพไม่ทับเส้นเดิมอย่างสมบูรณ์ดังนั้นฉันจึงปรับค่าออฟเซ็ตเล็กน้อย):

ผลลัพธ์

และไม่มีรูปหลายเหลี่ยม:

ผลลัพธ์ที่ไม่มีรูปหลายเหลี่ยม



แก้ไข:

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

from qgis.core import *
from qgis.gui import *

@qgsfunction(args='auto', group='Custom')
def func(feature, parent):
    polygon_layer = QgsMapLayerRegistry.instance().mapLayersByName( "polygon example_2" )[0]
    feat_list = []
    geoms = QgsGeometry.fromWkt('GEOMETRYCOLLECTION()')
    for polygon_feat in polygon_layer.getFeatures():
        if feature.geometry().intersects(polygon_feat.geometry()):
            intersection = feature.geometry().intersection(polygon_feat.geometry())
            feat_list.append(intersection)
    for x in feat_list:
        geoms = geoms.combine(x)
    return geoms

ฟังก์ชั่นแก้ไข

คลิกโหลดแล้วไปที่การแสดงออกfunc()แท็บและพิมพ์ หวังว่าผลลัพธ์ควรมีลักษณะดังต่อไปนี้ (ใช้คุณสมบัติของสไตล์เดียวกันที่กล่าวถึงข้างต้น):

ผลสุดท้าย


ฉันดูที่จริง แต่หยุดเมื่อฉันค้นพบที่get_featureต้องใช้ชื่อและค่าฟิลด์ ฉันมีเลเยอร์รูปหลายเหลี่ยมและต้องการใช้คุณสมบัติทั้งหมดในเลเยอร์นั้นเพื่อปกปิด เป็นไปได้ไหม
Chau

@Chau - โพสต์ที่แก้ไขแล้วเพื่อรวมวิธีการที่เป็นไปได้ :)
Joseph

1
อีกทางเลือกหนึ่งคือการละลายเลเยอร์รูปหลายเหลี่ยม
csk

1
@Joseph - เมื่อใช้ a Geometry Generatorจะfuncเรียกวิธีการสำหรับทุกคุณสมบัติในเลเยอร์ที่ใช้ในการออกแบบหรือไม่ ดังนั้นถ้าเลเยอร์บรรทัดของฉันมีคุณสมบัติ 3 อย่างดังนั้นfuncจะเรียกว่า 3 ครั้งและวาดผลลัพธ์เดียวกัน 3 ครั้ง
Chau

1
@Chau - ฉันคิดว่าคุณถูกต้องรหัสซ้ำผ่านแต่ละคุณสมบัติหลายครั้ง แก้ไขโพสต์เพื่อให้funcสามารถเรียกได้เฉพาะในแต่ละคุณลักษณะบรรทัดและจะดึงผลลัพธ์เพียงครั้งเดียว (ซึ่งน่าจะเป็นกรณีที่แสดงโดยเครื่องหมายจุดสุดยอดในรูปหลายเหลี่ยมก่อนหน้านี้จะซ่อนอยู่ใต้ที่ฉันพลาด) ขอบคุณที่ชี้นำสิ่งนี้ :)
โจเซฟ

3

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

from qgis.core import *
from qgis.gui import *
from qgis.utils import iface

@qgsfunction(args='auto', group='Custom')
def mask_line_with_polygon(mask_type, line_layer_name, polygon_layer_name_1, polygon_layer_name_2, feature, parent):
    line_layer = QgsMapLayerRegistry.instance().mapLayersByName( line_layer_name )[0]

    # This is the geometry outside the polygon mask.
    outside = QgsGeometry(feature.geometry())

    polygon_layer_names = [polygon_layer_name_1, polygon_layer_name_2]
    line_feature_extent = outside.boundingBox()

    geoms = QgsGeometry.fromWkt('MultiLineString()')

    for polygon_layer_name in polygon_layer_names:
        if polygon_layer_name is None or len(polygon_layer_name) == 0:
            continue

        # If the line and the polygon layers have different projections, handle them here.
        polygon_layer = QgsMapLayerRegistry.instance().mapLayersByName(polygon_layer_name)[0]
        trs = QgsCoordinateTransform(line_layer.crs(), polygon_layer.crs())
        polygon_extent = trs.transform(line_feature_extent)
        trs = QgsCoordinateTransform(polygon_layer.crs(), line_layer.crs())

        # Go through the features in the polygon layer, but only those within the line feature bounding box.
        for feature in polygon_layer.getFeatures(QgsFeatureRequest().setFilterRect(polygon_extent)):
            polygon_geometry = QgsGeometry(feature.geometry())

            # Transform the polygon to line space.
            polygon_geometry.transform(trs)

            if outside.intersects(polygon_geometry):
                if mask_type.lower() == 'outside':
                    inside = outside.intersection(polygon_geometry)

                    if inside.isMultipart():
                        for x in inside.asMultiPolyline():
                            geoms.addPart(x)
                    else:
                        geoms.addPart(inside.asPolyline())

                outside = outside.difference(polygon_geometry)

    if mask_type.lower() == 'inside':
        if outside.isMultipart():
            for x in outside.asMultiPolyline():
                geoms.addPart(x)
        else:
            geoms.addPart(outside.asPolyline())

    return geoms

แบบฝึกหัดนี้แสดงให้ฉันเห็นว่า QGIS ไม่ชอบการทำงานกับชุดข้อมูลขนาดใหญ่เกินไปและอัลกอริทึมนี้ที่มี QGIS หยุดทำงานบ่อยเกินไป ฉันสงสัยว่าตัวเรนเดอร์ QGIS ไม่ชอบเรนเดอร์ Geometry Generators ซึ่งใช้เวลานาน

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