Styling layer tertentu dengan menggunakan poligon di QGIS?

10

Saya memiliki lapisan garis dan lapisan poligon di QGIS:

Sebelum topeng

Saya ingin menata bagian lapisan garis di luar poligon menggunakan satu gaya dan bagian di dalam menggunakan gaya yang berbeda:

Setelah topeng

Saya tidak ingin membuat kumpulan data turunan, mis. klip layer garis dan gaya dua bagian.

Ini adalah kasus sederhana tetapi dalam proyek QGIS saya, saya memiliki +30 lapisan jadi saya pikir setiap campuran lapisan akan mengganggu lapisan yang mendasarinya.

Apakah mungkin melakukan hal seperti ini?

Saya tidak ingin menunjukkan lapisan poligon, hanya di sini untuk memvisualisasikan apa yang ingin saya lakukan.

Chau
sumber
1
Metode yang bagus! Saya pikir itu harus diposting sebagai jawaban alih-alih mengedit pertanyaan :)
Joseph
@ Joseph, sudah selesai!
Chau

Jawaban:

11

Bukan solusi yang sempurna tetapi Anda dapat menggunakan Geometry Generator yang menambahkan garis yang divisualisasikan untuk mewakili persimpangan. Anda kemudian dapat mengatur ini untuk tumpang tindih fitur garis asli.

Tambahkan layer simbol baru dengan mengklik tanda plus dan pilih Geometry generatortipe layer simbol sebagai. Setel tipe geoemtry ke LineString / MultiLineStringdan gunakan ekspresi berikut:

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

Anda perlu menambahkan detail tentang poligon spesifik Anda di mana:

  • polygonLayer adalah nama lapisan poligon Anda
  • fieldName adalah nama bidang
  • value adalah nilai fitur dari poligon spesifik Anda

Properti bergaya

Perhatikan bahwa untuk mewarnai garis visual, Anda mungkin perlu melakukannya dari properti Draw effect :

Menarik efek properti

Ini adalah hasilnya (perhatikan bahwa garis visual tidak tumpang tindih dengan garis asli sepenuhnya sehingga saya memodifikasi sedikit offset):

Hasil

Dan tanpa poligon:

Hasil tanpa poligon



Edit:

Jika Anda ingin ini diterapkan untuk setiap fitur garis yang memotong fitur poligon, buka Function Editor dan gunakan fungsi berikut (ubah nama polygon example_2untuk mencocokkan nama lapisan poligon Anda):

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

Editor fungsi

Klik Muat kemudian buka tab Ekspresi dan ketik func(). Semoga hasilnya akan terlihat seperti berikut (menggunakan properti gaya yang sama yang disebutkan di atas):

Hasil akhir

Yusuf
sumber
Saya benar-benar melihat itu tetapi berhenti ketika saya menemukan, yang get_featuremembutuhkan nama bidang dan nilai. Saya hanya memiliki lapisan poligon dan ingin menggunakan semua fitur pada layer itu untuk menutup. Apakah itu mungkin?
Chau
@ Chau - Posting yang diedit untuk memasukkan metode yang mungkin :)
Joseph
1
Pilihan lain adalah melarutkan lapisan poligon.
csk
1
@ Joseph - Ketika menggunakan a Geometry Generatoradalah metode yang funcdipanggil untuk setiap fitur pada layer di mana ia digunakan untuk styling? Jadi jika lapisan garis saya memiliki 3 fitur, maka funcdisebut 3 kali dan menggambar hasil yang sama 3 kali?
Chau
1
@ Chau - Saya pikir Anda benar, kode iterasi melalui setiap fitur beberapa kali. Mengedit pos sehingga funcsekarang seharusnya hanya dipanggil per setiap fitur garis dan hanya akan menggambar hasilnya satu kali (yang tampaknya seperti yang ditunjukkan oleh penanda titik di dalam poligon, sebelum ini disembunyikan di bawah yang saya lewatkan). Terima kasih telah menunjukkan ini :)
Joseph
3

Memperluas jawaban Joseph , saya menemukan fungsi ini. Ini menjelaskan sistem koordinat yang berbeda dan saya perlu mencari ke dalam dua lapisan masking, sehingga menangani itu juga. Lebih jauh lagi saya ingin bisa menutupi garis-garis di dalam poligon atau garis-garis di luar poligon.

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

Latihan ini telah menunjukkan kepada saya bahwa QGIS tidak terlalu suka bekerja dengan kumpulan data besar dan algoritme dengan QGIS ini terlalu sering menabrak saya. Saya menduga bahwa penyaji QGIS tidak suka membuat Pembuat Geometri yang memakan waktu.

Chau
sumber