QGISでポリゴンマスクを使用して特定のレイヤーのスタイルを設定しますか?


10

QGISにラインレイヤーとポリゴンレイヤーがあります。

マスク前

あるスタイルを使用してラインレイヤーの一部をポリゴンの外側にスタイルし、別のスタイルを使用して内側をパーツにしたいと思います。

マスク後

派生データセットを作成したくありません。ラインレイヤーをクリップし、2つのパーツのスタイルを設定します。

これは単純なケースですが、私のQGISプロジェクトでは+30のレイヤーがあるため、レイヤーのブレンドは基礎となるレイヤーを妨害すると思います。

このようなことをすることは可能ですか?

ポリゴンレイヤーは表示したくありません。ここでは、何をしたいかを視覚化します。


1
いい方法!私はそれが質問の編集ではなく回答として投稿されるべきだと思います:)
ジョセフ

@ジョセフ、やった!
Chau

回答:


11

完璧な解決策ではありませんが、交差点を表す視覚化された線を追加するジオメトリジェネレータを利用できます。次に、これを元のラインフィーチャと重複するように設定できます。

プラス記号をクリックして新しいシンボルレイヤーを追加し、Geometry generatorシンボルレイヤータイプとしてas を選択します。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 2017

1
@ジョセフ-を使用する場合、スタイリングに使用されるレイヤー上のすべての機能に対してGeometry Generatorメソッドがfunc呼び出されますか?ラインレイヤーに3つのフィーチャがある場合、func3回呼び出され、同じ結果を3回描画しますか?
Chau

1
@Chau-あなたは正しかったと思います、コードは各機能を何度も繰り返しました。ポストを編集して、func各ラインフィーチャごとにのみ呼び出され、結果が1回だけ描​​画されるようにしました(これは、ポリゴンの下にある頂点マーカーによって示されているように見えますが、これは、私が見逃した下に隠されていました)。これを指摘してくれてありがとう:)
Joseph

3

ジョセフの答えを拡張して、私はこの機能を思いつきました。これは異なる座標系を考慮しており、2つのマスキングレイヤーを検索する必要があったため、それも処理します。さらに、ポリゴンの内側のラインまたはポリゴンの外側のラインをマスクできるようにしたかったのです。

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レンダラーは、時間がかかるジオメトリジェネレーターをレンダリングしたくないと思います。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.