QGISで隣接するタイルIDを決定する方法は?


11

最近のトレーニングコースで、QGISがアトラスジェネレーターを使用して作成されたマップブックの次/前および上/下のページ番号を自動的に計算できるかどうかを尋ねられました。グリッドの幅と高さがわかっていれば、通常のグリッドに対してかなり合理的なラベル表現を作成できました。

しかし、その後、私たちの興味のある地区を含まないページを描画したくない現実的な例について考え始めました。たとえば、私の本拠地郡の1つです。

ここに画像の説明を入力してください

それで、今日の午後、私はpythonスクリプトを使って、各グリッドセルに興味のある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()

これはうまく機能します。

ここに画像の説明を入力してください

しかし、正直に言うと、全体が北へのテストポイントを作成してから、考えられるすべての隣人をテストするのは間違っているようです。しかし、私の脳を壊した午後の後、特定のグリッドセルの北隣が何であるかを判断するより良い方法を考えることはできませんか?

理想的には、印刷作曲家のテキストボックスに入れるのに十分な単純なものが欲しいのですが、それはあまりにも多くを求めていると思います。


片側に隣人がいない場合はどうなりますか。クローゼットセルの値を一方向にしたいですか、それとも空白にしますか?
radouxju

その場合、nullに満足しています。nullまたは空でない場合にのみ表示するようにラベルを簡単に設定できます。
イアンタートン

回答:


3

各ページ範囲(インデックスレイヤーから)をコンポーザーに正確にフィットさせず、代わりに隣接するページとオーバーラップする境界線がある場合(2番目のスクリーンショットに示すように)、インデックスレイヤーからラベルを使用できます。それらはマップの境界内にあります。

重複がない場合は、過去に(E&Wサセックスで偶然に)成功して使用した手法をMapInfoで複製することができます。 、シート番号とオフセットの方向の両方の属性を持つ、隣接するフィーチャへのオフセット。次に、ポイントレイヤーを使用してラベルを再度生成し、オフセットの方向を使用して、ラベルの向きを調整してより良い効果を実現しました。

私はこれを試したことはありませんが、新しいジオメトリジェネレーターのスタイリング機能を使用することで、QGISで別のデータレイヤーを生成することを避けることができる場合があります。


私は本当に他のポリゴンのラベルを使用することを考えるべきでした!:-)ジオメトリジェネレータ私はバウンディングボックスを描くことができますが、それは、グリッドを構築するために困難だと迅速な実験の後
イアンTurton

グリッドではなく、隣接するポリゴンにオフセットされたラベルポイントを生成するラインに沿って考えていました。別のオプションは、インデックスフィーチャのMBRを隣接フィーチャに展開して、ラベルを描画できるようにすることです。
アンディハーフット

遊びがあっただけで、ジオメトリジェネレーターのスタイリングによって生成されたジオメトリにはラベルが付けられていないようです。
アンディハーフット

8

実際には、アトラスを使用して印刷するタイルを決定するために必要な作業のほとんどを既に実行しました。ただし、ポイントは、必要なタイルIDのみを表示するようにすべてを調整する方法です。私のアイデアを示すために、この例では、以下に示すようにDEM画像とグリッドベクトルファイルを使用します。

ここに画像の説明を入力してください

まず、各グリッドのラベルを表示する必要があります。

レイアウトビューでは、グリッドをアトラスのカバレッジレイヤーとして使用し、2つのマップを作成しました。メインビューウィンドウマップと、以下に示すようにグリッドのみを表示するインデックスマップです。

ここに画像の説明を入力してください

その後、私は次のことをしました:

  1. インデックスマップのスケールを調整してグリッド範囲全体を表示し、スケールを修正しました
  2. ビュー範囲を修正して、を使用するときにマップがパンしないようにしました Preview atlas
  3. 私は有効になってOverviewあなたが下記を参照できるように、メインビューマップの範囲や場所を確認します:

ここに画像の説明を入力してください

メインビューウィンドウマップの場合、スケールを各グリッドブロックの範囲に固定しました。以下に示すように、何かが発生してもスケールが変更されないようにします。

ここに画像の説明を入力してください

インデックスマップを使用すると、メインビューマップウィンドウからグリッドをオフにしても、他のタイルを参照して各タイルのIDと位置を簡単に確認できます。たとえば、次のマップにはタイルID = 14があり、周囲のタイルIDを確認できます。

ここに画像の説明を入力してください

更新

周囲のレイアウトのIDではなく、周囲のレイアウトのページ番号インデックスを表示したいことに気付いたので、回答を更新します。

プロセスの理解を容易にするために、以下に示すように、インデックスマップのID番号を更新してレイアウトページ番号を表示します。

ここに画像の説明を入力してください

私が持っているIDは0(ゼロ)から始まるので、インデックスマップに表示される最初のグリッドのIDは3から始まります。したがって、AtlasのID番号から2を引いて1から始まるページ番号を変更します。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コメントありがとうございます。回答を更新しました。
アーマダン

キーマップ/グリッドの側面は規則的であるため、これはあなたの例(および彼の例)で機能します。それらがまっすぐではない場合、加算または減算する数(例では6)は、アトラスページによって異なるため、機能しません。
ビクター

2
仰るとおりです。グリッドが規則的でない場合、プロセスはより複雑になります。しかし、彼はそれを通常のグリッドに適用したいので、提案されたソリューションで適用された方法は機能します。
アフマダン

別の良いアイデアがある場合に備えて、事実に注意してください!特に私のグリッドは規則的ではないので!
ビクター

2

このソリューションは、長方形グリッドで機能し、自動です(手動で調整することなく、どのシナリオでも機能するはずです)。

ページ番号のあるグリッドがあると仮定しましょう。グリッドレイヤーとそのページ番号フィールドをパラメーターとして選択して、処理スクリプトを実行できます。スクリプトはright, left, above, below、グリッドレイヤーに4つのフィールド()を作成し、各グリッドセルの対応する隣接ページIDを計算します。次に、式(例:)を使用して、[% if( "left" is not NULL, 'to page' || "left", "" ) %]隣接ページのラベルを表示できます。

QGISリソース共有プラグインからリポジトリ(https://github.com/gacarrillor/QGIS-Resources.git)を追加して、スクリプトをインストールするだけです: ここに画像の説明を入力してください

ここに画像の説明を入力してください

使い方

スクリプトは、現在のグリッドセルと各交差セルの両方から境界ボックスの座標を比較することにより、関係(右、左、上、または下)を決定します。各リレーションについて、座標の1つが欠落していることがわかります。

リレーションがのabove場合、欠落している座標はですyMin。つまり、現在のグリッドセルの境界ボックスの他の3つの座標はすべて、上記のセルの境界ボックスに存在します。QGISバウンディングボックスは次の順序で定義されることに注意してください[xMin, yMin, xMax, yMax]

数値の例として、辺の長さが1の長方形を考えてみましょう。現在のセルの境界ボックスはとして定義されていbbox1=[0,0,1,1]ます。上記のセルの境界ボックスはとして定義されbbox2=[0,1,1,2]ます。bbox1のX座標はbbox2にありますが、bbox1のb yMin座標はbbox2のY座標にありません。

この方法で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.