(ラベルバッファを使用する代わりに)標高ラベルの下の等高線を中断する方法は?


32

標高ラベルの下の等高線を中断する方法はありますか?

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


ArcGIS?QGIS?カスタム?
ラギヤセルバーフム

1
私は、輪郭標識にQGISを使う
MAP

PostGISを必要とする回答を受け入れますか?
Scro

3
残念ながら:いいえ:)しかし、PostGISの問題を解決する方法はありますか?
MAP

回答:


22

はい、できます。通常、部分的に透明なバッファーをお勧めしますが、なぜこれを地図作成的に行うのかを理解しています。

これは遅くなる可能性があり、ラベルの移動先を手動で決定する必要がありますが、地図製作的に言えば、それは悪いことではありません!

これがスクリーンショットです...

ご覧のとおり、バッファはありません。下のラスターは影響を受けません。細い中間輪郭線を含めて、ELEV%50 <> 0の場合にのみ表示されるようにスタイルを設定しました

中断された等高線の例

私はこれをQGIS 2.12で行いました...あなたの走行距離は以前のバージョンによって異なる場合があります。

ここでは、各等高線に「ELEV」フィールドがあると仮定しています。

等高線をセグメント化する

  1. 処理とGRASSアルゴリズムv.split.lengthを使用して、等長線を等長のセグメントに分割します。メートルを使用している場合、マップ単位でラベルのサイズに近い長さを選択する必要があります。ここでは200mを使用しました。

    これにより、ファイルがはるかに大きくなります(スクリーンショットの機能カウントに注意してください)。

    これを回避するには、スタイル設定したい等高線のみ(50または100メートルごと)を生成して、すべての中間等高線を処理しないようにすることができます。

  2. このレイヤーに、showLabelという1桁の整数フィールドを追加します。デフォルトは0またはNULLです。

  3. このフィールドが1に設定されているセグメントにのみ表示されるようにラベルを変更します。これをラベルテキスト式に使用します...

    if ( "showlabel" is not null, "ELEV", "")
    

    if(expression、true-value、false-value)はかなり新しいと思います。古いバージョンを使用している場合は、CASE-ELSEを使用できます

  4. ラベルが表示されいるセグメントを除き、固定長セグメントがすべて描画されるように線のスタイルを変更します。したがって、2つのルールでルールベースのレンダリングを使用します

    Rule 1: "showLabel" is null
    Black, 0% transparent
    
    Rule 2: "showLabel" is not null
    Any colour, 100% transparent
    

    現在、デフォルトではすべての輪郭が表示されますが、ラベルは表示されません。

    ラベルを表示するセグメントを手動で編集します

    編集モードに入り、輪郭値を表示するセグメントを手動で選択showLabelし、選択したフィーチャの値を1に設定します。あなたは使用することができますCtrl(Ubuntuの/ Winの上、選択+ Cmd+ Ctrl高速なものに複数選択セグメントに+ Mac上/クリックして?)まで。

    これで、ラベルを表示したい輪郭を「クリップ」し、ギャップにラベルが表示されます。

この場合、ラベル設定は次のとおりです。

CRS: EPSG 27700 (Local UTM for UK, in meters)
Text size: 50 map units
Placement: Parallel, On Line

お役に立てば幸いです!


5
これは、私が想像できる唯一の完全に機能するソリューションです。非常に苦痛ですが、多くのラベルがある場合、このようにすべての地下水ヘッドマップ(年間数千)を行うことを想像することはできません。将来的にスタイルを介してこれを達成できる場合は素晴らしいと思います-カスタムラインパターンとラベルの繰り返し+オフセットが最善だからです。
ミロ

2
タスクを簡単にするいくつかのアイデア:ラベルを描画するために複数のセグメントを選択するには、[ポリゴンで選択]または[フリーハンドで選択]が便利です。また、別のアプローチとして、スクラッチラインレイヤーを作成して、輪郭を遮る線を描画し、場所による選択を行います。
アレクサンドルネト

7

「ラベル設定」タブの「バッファ」オプションを使用します。(レイヤープロパティダイアログの古いラベルオプションではなく、ラベルボタンを使用します。)これは、あなたがしたいと思うように等高線を消しませんが、ラベルを読みやすくします。


4
以前は考えもしませんでしたが、バッファーに色を割り当てる代わりに、選択したレイヤーに「ノックアウト」として適用することを選択できると便利です。
Scro

5
QGISの最新バージョンには透明なバッファがあるため、マップの他の部分への影響を減らすことができます。
ネイサンW

1
@MAPノックアウトは、その下のピクセルを消去します。それがオプションである場合、この場合、輪郭レイヤーをノックアウトすることを選択します。
Scro

1
ノックアウト-esri用語は「マスク」リソース
マイク

1
@MAP-開発者のスポンサーになるか、機能のリクエストを送信し、他の人の慈悲を待ちます。:)
Scro

5

現在のQGISの機能で最も近いのは、基になるグリッドに使用されるのと同じ標高値と配色に基づくテーブルからの色でハロー(または背景)効果を使用することです。もちろん、これは陰影起伏およびマップ内のハローの下にある他のすべてを考慮しません。ランダムカラーの例: ラベルのハロー効果のランダムな色 いくつかのコードを使用して、グリッドカラーを反映する関数としてこれを書き換えることができます。

理論的には、カスタムラインパターンとラベルリピート+オフセットを使用できるはずです。残念ながら、ラベルオフセットの設定はありません。

  • いくつかのテストの後、QGISにラベルを正確な間隔で他のどこにも配置することを強制することは不可能です(とにかく開始オフセットが欠落しています)
  • 20ライン-10スペース-70ライン-0スペースなどの開始オフセットを持つスペースのためにゼロmmのカスタムラインパターンを作成することは不可能です。したがって、ラベルは開始時に30 mmオフセットで100 mmごとに配置されます。すべての10mmの穴の中央。

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


2

最近同じ問題に遭遇した後、私はQGIS Pythonスクリプトを作成して、重い作業を実行しました。一部の(英国)テストデータ、Readme(ガイド)、および使用されるスタイルシートを含むスクリプトは、https://github.com/pjgeng/Contour-Labelsにあります。

要するに、スクリプトは、注釈付きの輪郭レイヤーと「ガイド」レイヤーという2つのベクターレイヤーを入力として使用します。後者は、目的のラベル位置で輪郭と交差するポリラインで構成されます。

次に、スクリプトは、輪郭間の距離と適用するラベルのインデックス輪郭間隔に基づいて機能し、ラベルポイントに回転値を追加し、最終的に元の輪郭レイヤーをクリップしてギャップを生成します。

最終結果のクローズアップ。

ユーザーが同じ領域内で異なる間隔で等高線図を作成する必要がある場合(つまり、ガイドが変更されない場合)、このアプローチは特にうまく機能します。欠点は、スクリプトの終了後にラベルの位置を変更できないことです。このため、ユーザーはガイドラインを調整し、元の入力に対してスクリプトを再実行する必要があります。以前はラベルの周りのバッファーで多くの作業を行い、中断された効果を作成しましたが、これはベクターデータドリブンマップでは審美的に不快であることが判明しました。

残念ながら、この時点でこれ以上写真を追加してプロセスを文書化または説明することはできません。

PS:リポジトリで提供されるスタイルレイヤーを使用する場合、ユーザーは、ラベリングメニューで「回転」、「ラベルを表示」、「常に表示」のカスタムフィールドを「アクティブ化」する必要があります。QGISの一部のインストールでは、これらはスタイルシートから自動的に適用されます-これを引き起こす原因はまだわかりません。


2

QGISコンターラベルマスキング問題の別のソリューションを次に示します。ここでは、QGISのSpatialite機能(現在はQGIS 3.x)と、ラベル配置用のジオメトリジェネレーターを利用しています。

この非常に動的なソリューションにより、すべてのラベルテキストのサイズとラベルの位置をすぐに変更でき、PDFベクターのエクスポートにも耐えられます。

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

これを可能にするには、次の部品が必要です。

  1. 「contours」と呼ばれる「LINESTRING」または「MULTILINESTRING」ベクトルレイヤー。2つのフィールドがあります。「fid」(Interger64 –主キー)、「elev」(文字列)
  2. 「scratch_lines」と呼ばれる「LINESTRING」ベクトルレイヤー(図の赤い線を参照)
  3. グローバルな等高線ラベルサイズを格納する「設定」と呼ばれるジオメトリレステーブル(QGISは現在SQLクエリでプロジェクト変数を使用できないため、これは簡単な回避策です):「fid」(Integer64-主キー)、「変数」 (文字列)、「値」(文字列)

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

  1. ルールベースのスタイリングを備えた「contours_with_labels」と呼ばれる仮想レイヤー:

    • ルール1:「ラベル」= 1…単純な線、不透明度0%
    • ルール2:ELSE…単純な行

    • ルール1の条件付きラベルテキスト:

      label = 1 THEN elev ELSE '' ENDの場合

    • テキスト配置用のジオメトリジェネレーターを使用:

      make_line(start_point($ geometry)、end_point($ geometry))

    • 可変テキストサイズの式文字列:

      属性(get_feature( 'settings'、 'variable'、 'contourlabel_size')、 'value')

最後に大事なことを言い忘れましたが、仮想レイヤーのSQLクエリを次に示します。

------------------------------------------------------------------------
-- select all contour lines that do not intersect any scratch lines
------------------------------------------------------------------------
select c.geometry,c.elev,0 as label 
from contours c,
       (select st_union(geometry) as geom from scratch_lines) as scr 
where not st_intersects(c.geometry,scr.geom)
------------------------------------------------------------------------

UNION

--------------------------------------------------------------------------------------------------------
-- create buffers around all scratch lines (bufferwidth = length(elevation_text) * txtsize/3),
-- get st_difference between contour lines and buffers
-- and set attribute "label" to 0
--------------------------------------------------------------------------------------------------------
select st_difference(c.geometry,buf.geom) as geom,c.elev,0 as label 
from 
  (select c.fid,st_union(st_buffer(scr.geometry,length(c.elev) * txtsize.value / 3)) as geom 
      from scratch_lines scr, 
              contours c, 
              (select cast(value as integer) as value from settings where variable = 'contourlabel_size') txtsize 
      where st_intersects(scr.geometry,c.geometry) 
      group by c.fid) as buf,
  contours c 
where c.fid = buf.fid
group by c.fid
--------------------------------------------------------------------------------------------------------

UNION

--------------------------------------------------------------------------------------------------------
-- create buffers around all scratch lines (bufferwidth = length(elevation_text) * txtsize/3),
-- get st_intersection between contour lines and buffers
-- and set attribute "label" to 1
--------------------------------------------------------------------------------------------------------
select st_intersection(st_buffer(scr.geometry,length(c.elev) * txtsize.value / 3),c.geometry) as geom,c.elev,1 as label 
from scratch_lines scr,
        contours c,
        (select cast(value as integer) as value from settings where variable = 'contourlabel_size') txtsize 
where st_intersects(c.geometry,scr.geometry)

それでおしまい。

これを可能にしてくれた熱狂的な人々に感謝します!


私は言わなければならない、私は結果に感銘を受けています。組み込みオプションを取得するまで(もしあれば)、これは間違いなく最もクリーンな方法です。再び仮想レイヤーが助けになります。
ガブリエルC.

私は本当に自分自身に感銘を受けました。しかし、それは本当に大きな輪郭層に耐えることができますか?
クリストフ

そして、テスト後、GeoPackagesのデータでも機能することを非常に嬉しく思います!Spatialiteに基づいているため、確認したかった。私は複数回まで投票可能性がしたい...
ガブリエルC.

私見、クエリはQGIS内で実行されているため、どのファイル形式からも独立しています。したがって、CSVでも動作するはずです。
クリストフ

話の終わりではないようです。今日の調査の後、仮想レイヤーSQLクエリ内でQGIS式関数を使用できることに気付きました:gis.stackexchange.com/questions/320991/…。ラベルマスキングを高速化するために、さらに多くの機能があります(スケール依存クエリまたは空間インデックスのより良い使用を考えています)。
クリストフ

1

このスレッドMartin を覚えていますか?あなたの問題の解決策に近づくために私が考えることができる唯一の方法は、輪郭レイヤーをクリップされた輪郭レイヤーでオーバーレイし、これをラベル付けに使用し、ラベルの下の輪郭をマスクする線色を中立なものに変更することです、邪魔にならずに望みます。N.

後で追加:2番目の答えであるこのスレッドを見る価値があるかもしれません。おそらく、輪郭を切り取るのに使用されるバッファーレイヤーを使用して、輪郭線を壊すことが答えかもしれません。


0

ESRIブログエントリ:http : //blogs.esri.com/esri/arcgis/2011/11/28/variable-depth-masking-contour-label-example/

等高線ラベルの可変深度マスキングには、3つのステップが含まれます。

1ラベルから注釈を作成、2フィーチャアウトラインマスクツールを使用してマスクを作成、3 [高度な描画オプション]> [マスキング設定]を使用してマスクがマスクするレイヤーを指定します。


これはどのように実装できるかを示していますが、実際には質問には答えていません。
暗闇

0

ラベルをより完璧にするために、仮想レイヤーのSQLクエリを変更して、等高線と平行に走るスクラッチラインを考慮しました(以下の解決策を参照)。

古いバージョン ここに画像の説明を入力してください

新しいバージョン ここに画像の説明を入力してください

そして、これが仮想レイヤーの新しいSQLです。

------------------------------------------------------------------------
-- select all contour lines that do not intersect any scratch lines
------------------------------------------------------------------------
select c.geometry,c.elev,0 as label 
from contours c,
   (select st_union(geometry) as geom from scratch_lines) as scr 
where not st_intersects(c.geometry,scr.geom)
------------------------------------------------------------------------

UNION

--------------------------------------------------------------------------------------------------------
-- create buffers around all intersection points (bufferwidth = length(elevation_text) * txtsize/2.5),
-- get st_difference between contour lines and buffers
-- and set attribute "label" to 0
--------------------------------------------------------------------------------------------------------
select st_difference(c.geometry,buf.geom) as geom,c.elev,0 as label 
from contours c,
(select c.fid,st_union(st_buffer(st_intersection(c.geometry,scr.geometry),length(c.elev) * txtsize.value / 3)) as geom
from contours c, scratch_lines scr, (select cast(value as integer) as value from settings where variable = 'contourlabel_size') txtsize
where st_intersects(c.geometry,scr.geometry)
group by c.fid) as buf
where c.fid = buf.fid
--------------------------------------------------------------------------------------------------------

UNION

--------------------------------------------------------------------------------------------------------
-- create buffers around all intersection points (bufferwidth = length(elevation_text) * txtsize/2.5),
-- get st_intersection between contour lines and buffers
-- and set attribute "label" to 1
--------------------------------------------------------------------------------------------------------
select st_intersection(c.geometry,st_buffer(st_intersection(c.geometry,scr.geometry),length(c.elev) * txtsize.value / 3)) as geom,c.elev,1 as label 
from contours c, 
 scratch_lines scr,
 (select cast(value as integer) as value from settings where variable = 'contourlabel_size') txtsize 
where st_intersects(c.geometry,scr.geometry)

0

元の質問に関連する小さな補遺。

「ジオメトリジェネレータ」スタイリングを使用して、QGIS 3.10の等高線を単純化および平滑化できるという事実を認識していないすべての人のために:

smooth(単純化($ geometry、2)、2)

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

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