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
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
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.
Untuk layer ini, tambahkan bidang integer 1 digit yang disebut showLabel . Default ke 0 atau NULL.
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
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
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.
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.
@ 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:
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.
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.
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.
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!
Untuk memungkinkan ini kita perlu bagian-bagian berikut:
Lapisan vektor "LINESTRING" atau "MULTILINESTRING" disebut "kontur" dengan 2 bidang: "fid" (Interger64 - kunci utama), "elev" (String)
Lapisan vektor "LINESTRING" yang disebut "scratch_lines" (lihat garis merah di gambar)
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)
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
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!
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?
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
Versi baru
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)
Untuk semua yang tidak menyadari fakta bahwa kita dapat menggunakan gaya "Geometry generator" untuk menyederhanakan dan menghaluskan garis kontur kita di QGIS 3.10:
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.
Jawaban:
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
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
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.
Untuk layer ini, tambahkan bidang integer 1 digit yang disebut showLabel . Default ke 0 atau NULL.
Ubah label untuk hanya ditampilkan pada segmen tempat bidang ini disetel ke 1. Gunakan ini untuk ekspresi teks label ...
Saya pikir jika (ekspresi, nilai sejati, nilai salah) cukup baru; jika menggunakan versi yang lebih lama, Anda dapat menggunakan CASE-ELSE
Ubah gaya garis sehingga semua segmen panjang tetap digambar, kecuali segmen tempat label ditampilkan. Jadi gunakan rendering Berbasis Rule dengan dua aturan
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
showLabel
ke 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:
Semoga itu bisa membantu!
sumber
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.
sumber
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: 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.
sumber
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.
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.
sumber
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!
Untuk memungkinkan ini kita perlu bagian-bagian berikut:
Lapisan virtual bernama "contours_with_labels" dengan gaya berbasis aturan:
Aturan 2: LAIN ... garis sederhana
dan teks label bersyarat untuk Aturan 1:
dan last but not least, inilah query SQL untuk lapisan virtual:
Itu dia.
Terima kasih banyak kepada semua orang yang antusias ini yang memungkinkan hal ini!
sumber
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?
sumber
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
Versi baru
Dan inilah SQL baru untuk lapisan virtual:
sumber
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:
sumber
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.
sumber