Bagaimana cara mengganggu garis kontur di bawah label elevasi (alih-alih menggunakan buffer label)?

32

Apakah ada cara untuk memotong garis kontur di bawah label ketinggian?

masukkan deskripsi gambar di sini

PETA
sumber
ArcGIS? QGIS? Adat?
Ragi Yaser Burhum
1
Saya menggunakan qgis untuk pelabelan kontur
PETA
Apakah Anda menerima jawaban yang memerlukan PostGIS?
Scro
3
sayangnya: tidak :) Tapi, apakah ada cara untuk menyelesaikan masalah dengan PostGIS?
PETA

Jawaban:

22

Ya, bisa dilakukan. Biasanya saya menyarankan buffer transparan sebagian, tapi saya mengerti mengapa Anda ingin melakukan ini secara kartografis.

Ini bisa lambat, dan Anda harus memutuskan secara manual ke mana Anda ingin label pergi - tetapi secara kartografis, itu bukan hal yang buruk!

Ini tangkapan layar ...

Seperti yang Anda lihat, tidak ada buffer. Raster di bawahnya tidak terpengaruh. Saya telah menyertakan garis kontur menengah yang lebih tipis, dan menatanya sehingga hanya ditampilkan ketika ELEV% 50 <> 0

contoh garis kontur terputus

Saya sudah melakukan ini di QGIS 2.12 ... jarak tempuh Anda mungkin berbeda dengan versi sebelumnya.

Saya berasumsi di sini Anda memiliki bidang "ELEV" pada setiap garis kontur.

Segmentasikan garis kontur

  1. Gunakan pemrosesan dan algoritma GRASS v.split.length untuk membagi kontur Anda menjadi segmen dengan panjang yang sama. Anda harus memilih panjang yang akan mendekati ukuran label Anda di unit peta, dengan asumsi Anda menggunakan meter. Di sini saya menggunakan 200m.

    Hati-hati dengan ini karena ini akan membuat file Anda jauh, jauh lebih besar (perhatikan fitur yang diperhitungkan dalam tangkapan layar).

    Untuk menyiasatinya, Anda mungkin ingin membuat hanya garis kontur yang ingin Anda gaya (misalnya setiap 50 atau 100 meter) untuk menghindari pemrosesan semua garis kontur perantara.

  2. Untuk layer ini, tambahkan bidang integer 1 digit yang disebut showLabel . Default ke 0 atau NULL.

  3. Ubah label untuk hanya ditampilkan pada segmen tempat bidang ini disetel ke 1. Gunakan ini untuk ekspresi teks label ...

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

    Saya pikir jika (ekspresi, nilai sejati, nilai salah) cukup baru; jika menggunakan versi yang lebih lama, Anda dapat menggunakan CASE-ELSE

  4. Ubah gaya garis sehingga semua segmen panjang tetap digambar, kecuali segmen tempat label ditampilkan. Jadi gunakan rendering Berbasis Rule dengan dua aturan

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

    Sekarang, semua kontur akan ditampilkan secara default, tetapi tidak ada label.

    Edit segmen secara manual di mana Anda ingin menampilkan label

    Masuk ke mode edit dan secara manual pilih segmen di mana Anda ingin menampilkan nilai kontur, dan atur nilai showLabelke 1 untuk fitur yang dipilih. Anda dapat menggunakan Ctrl+ pilih (di Ubuntu / Menang, Cmd+ Ctrl+ Klik / di Mac?) Untuk segmen multi-pilih untuk mempercepat.

    Ini sekarang harus 'klip' ​​kontur di mana Anda ingin label untuk ditampilkan, dan label akan ditampilkan di celah.

Dalam hal ini, pengaturan label saya adalah:

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

Semoga itu bisa membantu!

Steven Kay
sumber
5
Ini adalah satu-satunya solusi yang bisa saya bayangkan. Sangat menyakitkan meskipun jika ada banyak label, saya tidak bisa membayangkan melakukan semua peta kepala air tanah saya (ribuan per tahun) dengan cara ini. Akan lebih bagus jika di masa depan ini dapat dicapai melalui gaya - karena yang terbaik adalah pola garis kustom dan label repeat + offset.
Miro
2
Hanya beberapa ide untuk memudahkan tugas: Untuk memilih beberapa segmen untuk menggambar label, Pilih dengan Poligon atau Pilih dengan Freehand bisa berguna. Juga, pendekatan lain akan membuat lapisan garis awal untuk menggambar garis yang memotong kontur, dan kemudian melakukan Pilih berdasarkan lokasi.
Alexandre Neto
7

Saya menggunakan opsi "Buffer" pada tab "Label setting". (Menggunakan tombol label, bukan opsi label lama pada dialog properti layer.) Ini tidak menghapus garis kontur, seperti yang saya bayangkan Anda ingin lakukan, tetapi itu membuat label terbaca.

Scro
sumber
4
Saya tidak pernah memikirkannya sebelumnya, tetapi akan lebih mudah jika alih-alih menetapkan warna untuk buffer, Anda dapat memilih untuk menerapkannya sebagai 'sistem gugur' ke lapisan yang dipilih.
Scro
5
Versi terbaru QGIS memiliki buffer transparan sehingga Anda dapat mengurangi dampak pada bagian lain dari peta.
Nathan W
1
@ MAP KO menghapus piksel di bawahnya. Jika itu pilihan, dalam hal ini Anda akan memilih untuk menghapus KO lapisan kontur.
Scro
1
knockout - istilah esri adalah "masking" resources.arcgis.com/en/help/main/10.1/index.html#//…
mike
1
@ MAP - Mensponsori pengembang, atau mengirim permintaan fitur dan menunggu kebaikan orang lain. :)
Scro
5

Saya pikir yang paling dekat dengan kemampuan QGIS saat ini adalah menggunakan efek halo (atau latar belakang) dengan warna yang bersumber dari tabel yang akan didasarkan pada nilai ketinggian dan skema warna yang sama seperti yang digunakan untuk grid yang mendasarinya. Tentu saja ini tidak akan memperhitungkan hillshade dan segala sesuatu yang lain di bawah lingkaran cahaya di peta. Contoh warna acak: warna acak untuk efek halo label Dengan sedikit kode ini dapat ditulis ulang sebagai fungsi untuk mencerminkan warna kotak.

Secara teori, mungkin untuk menggunakan pola garis khusus dan label repeat + offset . Sayangnya tidak ada pengaturan offset label.

  • setelah beberapa pengujian tidak mungkin untuk memaksa QGIS untuk ketat dengan menempatkan label pada interval yang tepat dan tidak di tempat lain (+ toh toh start offset yang hilang)
  • tidak mungkin untuk membuat pola garis khusus dengan nol mm untuk ruang untuk memiliki offset mulai seperti 20 garis - 10 ruang - 70 garis - 0 ruang - sehingga label akan ditempatkan setiap 100mm dengan 30mm offset di awal - artinya label akan berada di tengah setiap lubang 10mm.

masukkan deskripsi gambar di sini

Miro
sumber
2

Setelah mengalami masalah yang sama baru-baru ini saya telah mengumpulkan skrip Python QGIS untuk melakukan pengangkatan berat. Script termasuk beberapa data pengujian (UK), Readme (Guide) dan style sheet yang digunakan dapat ditemukan di https://github.com/pjgeng/Contour-Labels

Singkatnya skrip menggunakan dua lapisan vektor sebagai input - lapisan kontur beranotasi dan lapisan "panduan". Yang terakhir terdiri dari polyline yang memotong kontur di lokasi label yang diinginkan.

Script kemudian bekerja berdasarkan jarak antara kontur dan interval kontur indeks yang label untuk menerapkan, menambahkan nilai rotasi ke titik-titik label dan akhirnya klip lapisan kontur asli untuk menghasilkan kesenjangan.

Closeup dari hasil akhir.

Pendekatan ini bekerja sangat baik jika pengguna harus menghasilkan peta kontur pada interval yang berbeda di area yang sama (yaitu panduan tidak berubah). Kelemahan adalah ketidakmampuan untuk mengubah posisi label setelah skrip selesai. Untuk ini, pengguna harus menyesuaikan garis panduan dan menjalankan kembali skrip terhadap input asli. Saya sebelumnya bekerja dengan buffer di sekitar label banyak untuk menciptakan efek terganggu, tetapi ini ternyata tidak menyenangkan secara estetika pada peta yang digerakkan oleh data vektor.

Sayangnya saya tidak dapat menambahkan gambar lagi saat ini untuk mendokumentasikan atau mengilustrasikan proses lebih lanjut.

PS: Jika menggunakan lapisan gaya yang disediakan dalam repositori, pengguna mungkin perlu "mengaktifkan" bidang khusus untuk "Rotasi", "Tampilkan Label" dan "Selalu Tampilkan" di menu label. Pada beberapa instalasi QGIS ini diterapkan secara otomatis dari stylesheet - Saya belum menemukan apa yang menyebabkannya.

Phil G
sumber
2

Berikut adalah solusi lain untuk masalah kontur-label-masking QGIS, di mana saya memanfaatkan fungsionalitas Spatialite QGIS (saat ini QGIS 3.x) bersama-sama dengan generator geometri untuk penempatan label.

Solusi yang sangat dinamis ini memungkinkan kita untuk mengubah semua ukuran teks label dan posisi label dengan segera, dan bahkan bertahan dari ekspor vektor PDF!

masukkan deskripsi gambar di sinimasukkan deskripsi gambar di sinimasukkan deskripsi gambar di sinimasukkan deskripsi gambar di sini

Untuk memungkinkan ini kita perlu bagian-bagian berikut:

  1. Lapisan vektor "LINESTRING" atau "MULTILINESTRING" disebut "kontur" dengan 2 bidang: "fid" (Interger64 - kunci utama), "elev" (String)
  2. Lapisan vektor "LINESTRING" yang disebut "scratch_lines" (lihat garis merah di gambar)
  3. Tabel tanpa geometri yang disebut "pengaturan" untuk menyimpan ukuran label kontur global (ini adalah solusi sederhana, karena QGIS tidak dapat menggunakan variabel Proyek dalam permintaan SQL sekarang): "fid" (Integer64 - kunci utama), "variabel" (String), “value” (String)

masukkan deskripsi gambar di sini

  1. Lapisan virtual bernama "contours_with_labels" dengan gaya berbasis aturan:

    • Aturan 1: “label” = 1 ... garis sederhana, opacity 0%
    • Aturan 2: LAIN ... garis sederhana

    • dan teks label bersyarat untuk Aturan 1:

      KASUS KETIKA label = 1 KEMUDIAN ketinggian ELSE AKHIR

    • dengan generator Geometri untuk penempatan teks:

      make_line (start_point ($ geometry), end_point ($ geometry))

    • dan String Ekspresi untuk ukuran teks variabel:

      atribut (get_feature ('pengaturan', 'variabel', 'contourlabel_size'), 'nilai')

dan last but not least, inilah query SQL untuk lapisan virtual:

------------------------------------------------------------------------
-- 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)

Itu dia.

Terima kasih banyak kepada semua orang yang antusias ini yang memungkinkan hal ini!

christoph
sumber
Saya harus mengatakan, saya terkesan dengan hasilnya. Sampai kita mendapatkan opsi bawaan (jika pernah), ini jelas merupakan cara terbersih. Lapisan virtual untuk menyelamatkan, lagi.
Gabriel C.
Aku memang terkesan oleh diriku sendiri. Tapi, bisakah ia bertahan dengan lapisan kontur yang sangat besar?
christoph
Dan saya sangat senang, setelah mengujinya, itu juga berfungsi dengan data di GeoPackages! Saya ingin memverifikasi karena didasarkan pada Spatialite. Seandainya saya bisa memilih lebih dari satu kali ...
Gabriel C.
IMHO, tidak tergantung dari format file apa pun, karena kueri berjalan di dalam QGIS. Jadi itu bahkan harus bekerja dengan CSV.
christoph
Sepertinya itu bukan akhir dari cerita. Setelah penelitian hari ini, saya menyadari bahwa kita dapat menggunakan fungsi ekspresi QGIS di dalam query SQL layer virtual: gis.stackexchange.com/questions/320991/… . Jadi ada banyak lagi yang akan datang, yang akan mempercepat label masking (Saya sedang memikirkan pertanyaan tergantung skala atau penggunaan indeks spasial yang lebih baik).
Christoph
1

Apakah Anda ingat utas ini Martin? Satu-satunya cara saya bisa memikirkan untuk mendekati solusi untuk masalah Anda adalah dengan overlay lapisan kontur Anda dengan lapisan kontur terpotong, gunakan ini untuk memberi label dan mengubah warna garis menjadi sesuatu yang netral yang akan menutupi kontur di bawah label, orang berharap tanpa terlalu mengganggu. N.

Ditambahkan nanti: mungkin layak untuk melihat utas ini juga, jawaban kedua. Mungkin melanggar garis kontur mungkin merupakan jawaban, mungkin menggunakan lapisan penyangga yang digunakan untuk klip kontur?

nhopton
sumber
1

Untuk membuat label lebih sempurna, saya mengubah kueri SQL dari lapisan virtual untuk menghormati garis awal yang berjalan paralel ke garis kontur (lihat solusi di bawah):

Versi lama masukkan deskripsi gambar di sini

Versi baru masukkan deskripsi gambar di sini

Dan inilah SQL baru untuk lapisan virtual:

------------------------------------------------------------------------
-- 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)
christoph
sumber
1

Adendum kecil terkait dengan pertanyaan awal.

Untuk semua yang tidak menyadari fakta bahwa kita dapat menggunakan gaya "Geometry generator" untuk menyederhanakan dan menghaluskan garis kontur kita di QGIS 3.10:

smooth (simplify ($ geometry, 2), 2)

masukkan deskripsi gambar di sini

christoph
sumber
0

Entri blog ESRI: http://blogs.esri.com/esri/arcgis/2011/11/28/variable-depth-masking-contour-label-example/

Penyamitan dengan kedalaman variabel untuk label kontur melibatkan tiga langkah:

1membuat anotasi dari label, 2 menggunakan alat Fitur Garis Besar Masker untuk membuat topeng, dan 3 menggunakan Pilihan Gambar Lanjut> pengaturan Masking untuk menentukan lapisan mana topeng akan ditutup.

Jenny
sumber
Ini menunjukkan bagaimana itu bisa diterapkan, tetapi itu tidak benar-benar menjawab pertanyaan.
underdark