Yükseklik etiketlerinin altındaki kontur çizgileri nasıl kesilir (etiket tamponları kullanmak yerine)?


32

Bir yükseklik etiketinin altındaki kontür çizgisini kesmenin bir yolu var mı?

görüntü tanımını buraya girin


ArcGIS? QGIS? Özel?
Ragi Yaser Burhum

1
Kontur etiketlemesi için qgis kullanıyorum
MAP

PostGIS gerektiren bir cevabı kabul eder misiniz?
Scro 5'13

3
ne yazık ki: hayır :) Ama PostGIS ile sorunu çözmenin bir yolu var mı?
MAP

Yanıtlar:


22

Evet, yapılabilir. Normalde kısmen şeffaf bir tampon öneririm, ancak bunu neden kartografik olarak yapmak istediğinizi anlıyorum.

Bu yavaş olabilir ve etiketlerin nereye gitmesini istediğinize elle karar vermeniz gerekir - ancak kartografik olarak konuşursanız, bu kötü bir şey değil!

İşte bir ekran görüntüsü ...

Gördüğünüz gibi tampon yok. Altındaki raster etkilenmez. Daha ince orta kontur çizgileri ekledim ve onları stillendirdik, böylece ELEV% 50 <> 0

kesintili kontur çizgileri örneği

Bunu QGIS 2.12 de yaptım ... kilometreniz önceki sürümlere göre değişebilir.

Burada her kontur çizgisinde bir "ELEV" alanı olduğunu varsayıyorum.

Kontur çizgilerini bölümlere ayır

  1. Konturlarınızı eşit uzunlukta bölümlere ayırmak için işleme ve GRASS algoritmasını v.split.length kullanın. Metreleri kullandığınız varsayılarak, harita birimlerinde etiketinizin boyutuna yakın olacak bir uzunluk seçmeniz gerekir. Burada 200m kullandım.

    Dosyanızı çok daha büyük hale getireceğinden bu konuda dikkatli olun (özelliğin ekran görüntüsünde önemli olduğunu unutmayın).

    Bunu aşmak için, tüm orta kontur çizgilerini işlemekten kaçınmak için yalnızca stillendirmek istediğiniz kontür çizgilerini (örneğin her 50 veya 100 metrede) oluşturmak isteyebilirsiniz.

  2. Bu katmana, showLabel adlı 1 basamaklı bir tamsayı alanı ekleyin . Varsayılan 0 veya NULL.

  3. Etiketi yalnızca bu alanın 1 olarak ayarlandığı bir segmentte gösterilecek şekilde değiştirin. Bunu etiket metni ifadesi için kullanın ...

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

    Bence (ifade, gerçek değer, yanlış değer) oldukça yenidir; daha eski bir sürüm kullanıyorsanız, CASE-ELSE kullanabilirsiniz.

  4. Çizgi stilini değiştirin, böylece etiketin gösterildiği bölümler hariç , sabit uzunluktaki bölümlerin tümü çizilir . Dolayısıyla Kural Tabanlı renderlemeyi iki kuralla kullanın

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

    Şimdi, tüm konturlar varsayılan olarak gösterilecek, ancak etiket göstermeyecektir.

    Etiket göstermek istediğiniz bölgeleri manuel olarak düzenleyin

    Gidin düzenleme modunda ve elle ekrana kontur değerlerini istediğiniz bölümleri seçin ve değerini ayarlamak showLabelseçilen özellikler için 1. İşleri hızlandırmak için çoklu seçim yapmak için Ctrl+ select'i (Ubuntu / Win'de, Cmd+ Ctrl+ Mac'te / Mac'te mi?)) Kullanabilirsiniz .

    Bu, etiketlerin gösterilmesini istediğiniz konturları 'kırpmalıdır' ve etiketler boşluklarda gösterilecektir.

Bu durumda, etiket ayarlarım:

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

Umarım yardımcı olur!


5
Hayal edebileceğim tek çalışan tamamen çözüm budur. Çok acı verici olsa da, çok fazla etiket varsa, tüm yeraltı suyu kafa haritalarımın (yılda binlerce) bu şekilde yapıldığını hayal bile edemiyorum. Gelecekte bu stil yoluyla elde edilebilirse harika olurdu - en iyisi özel çizgi deseni ve etiket tekrarı + ofseti olabilir.
Miro

2
Görevi kolaylaştırmak için yalnızca bazı fikirler: Etiketi çizmek için birden fazla segment seçmek için, Çokgen Seç veya Serbest Çizim ile Seç kullanışlı olabilir. Ayrıca, başka bir yaklaşım, kontürleri kesen çizgileri çizmek için bir çizik çizgi katmanı oluşturmak ve ardından konuma göre bir Seçim yapmak olacaktır.
Alexandre Neto,

7

"Label setting" sekmesindeki "Buffer" seçeneğini kullanıyorum. (Katman özellikleri iletişim kutusundaki eski etiketler seçeneğini değil, etiketler düğmesini kullanın.) Bu, yapmak istediğinizi düşündüğüm gibi kontur çizgisini silmez, ancak etiketi okunaklı hale getirir.


4
Bunu daha önce hiç düşünmemiştim, ancak tampon için bir renk atamak yerine, onu seçilen katmanlara bir 'nakavt' olarak uygulamayı tercih ederseniz uygun olurdu.
Scro

4
QGIS'in en yeni sürümü şeffaf tamponlara sahiptir, böylece haritanın diğer bölümleri üzerindeki etkisini azaltabilirsiniz.
Nathan W,

1
@ HARİTA Nakavt, altındaki pikselleri siler. Bu bir seçenek olsaydı, bu durumda kontur katmanını nakavt etmeyi seçtiniz.
Scro


1
@ Harita - Bir geliştiriciye sponsor olun veya bir özellik isteği gönderin ve başkalarının yardımseverliğini bekleyin. :)
Scro

5

Mevcut QGIS yetenekleri ile elde edebileceği en yakın şeyin, altta yatan ızgara için kullanılan yükseklik değerine ve renk şemasına dayanacak olan tablodan elde edilen renkle halo (veya arka plan) efekti kullanmak olduğunu düşünüyorum . Tabii ki bu, tepe gölgesini ve haritadaki halo altındaki her şeyi hesaba katmaz . Rastgele renk örneği: etiketlerin halo etkisi için rastgele renk Bazı kod biti ile bu, ızgara rengini yansıtan bir işlev olarak yeniden yazılabilir.

Teoride, özel çizgi deseni ve etiket tekrarı + ofseti kullanmak mümkün olmalıdır . Ne yazık ki etiket ofset ayarı yoktur.

  • Bazı testlerden sonra, QGIS'in etiketleri tam aralıklarla ve başka hiçbir yere koyma konusunda katı olmaya zorlaması imkansızdır (+ yine de başlangıç ​​kayması)
  • 20 satır - 10 boşluk - 70 satır - 0 boşluk - başlangıçta ofset için boşluk için sıfır mm özel çizgi deseni oluşturmak imkansız, böylece etiket başlangıçta 30 mm ofset ile her 100 mm'de bir yerleştirilir - yani etiket her 10 mm'lik deliğin ortasında.

görüntü tanımını buraya girin


2

Son zamanlarda aynı problemle karşılaştıktan sonra ağır kaldırma işlemini gerçekleştirmek için bir QGIS Python senaryosu hazırladım. Bazı (İngiltere) test verileri, Readme (Guide) ve kullanılan stil sayfalarını içeren komut dosyası https://github.com/pjgeng/Contour-Labels adresinde bulunabilir.

Kısacası komut dosyası, giriş olarak iki vektör katmanını kullanır - açıklamalı kontur katmanı ve bir "kılavuzlar" katmanı. İkincisi, konturları istenen etiket lokasyonlarında kesişen polillerden oluşur.

Komut daha sonra konturlar arasındaki mesafeye ve etiketlerin uygulanacağı, etiket noktalarına bir dönme değeri ekleyen endeks kontur aralığı arasındaki mesafeye bağlı olarak çalışır ve sonunda boşlukları üretmek için orijinal kontur katmanını klipler.

Son sonucun çekimi.

Yaklaşım özellikle kullanıcının aynı alanda farklı aralıklarla kontur haritaları üretmesi gerektiğinde iyi çalışır (örn. Kılavuzlar değişmez). Bir dezavantaj, kod tamamlandıktan sonra etiket konumunu değiştirememesidir. Bunun için kullanıcının kılavuz çizgilerini ayarlaması ve betiği orijinal girdiyle tekrar çalıştırması gerekir. Daha önce kesikli efekt oluşturmak için etiketlerin etrafındaki tamponlarla çok çalıştım, ancak bunun vektör veriye dayalı haritalarda estetik açıdan nahoş olduğu ortaya çıktı.

Ne yazık ki, işlemi daha fazla belgelemek veya göstermek için şu anda daha fazla resim ekleyemiyorum.

Not: Depoda sağlanan stil katmanlarını kullanıyorsanız, etiketleme menüsünde "Döndürme", "Etiketi Göster" ve "Her Zaman Göster" için özel alanları "etkinleştirmeleri" gerekebilir. Bazı QGIS kurulumlarında bunlar otomatik olarak stil sayfasından uygulanır - Buna henüz neyin sebep olduğunu bulamadım.


2

İşte QGIS kontur-etiket-maskeleme problemi için başka bir çözüm, burada QGIS Spatialite işlevselliğini (şu anda QGIS 3.x) etiket yerleştirme için bir geometri üreteci ile birlikte kullanıyorum.

Bu çok dinamik çözüm, tüm etiket metni boyutlarını ve etiket konumlarını hemen değiştirmemize olanak sağlar ve hatta bir PDF vektörü dışa aktarma işleminden de kurtulabilir!

görüntü tanımını buraya giringörüntü tanımını buraya giringörüntü tanımını buraya giringörüntü tanımını buraya girin

Bunu mümkün kılmak için aşağıdaki parçalara ihtiyacımız var:

  1. 2 alanlı “konturlar” olarak adlandırılan “DİNLENME” veya “ÇOKLU ORTALAMA” vektör katmanı: “fid” (Interger64 - birincil anahtar), “elev” (Dize)
  2. “Scratch_lines” adı verilen “LINESTRING” vektör katmanı (resimdeki kırmızı çizgilere bakın)
  3. Global kontur etiketi boyutunu saklamak için “ayarlar” adı verilen ve geometri içermeyen bir tablo (bu basit bir çözümdür, çünkü QGIS artık SQL sorgularında Proje değişkenlerini kullanamaz): “fid” (Integer64 - birincil anahtar), “değişken” (Dize), “değer” (Dize)

görüntü tanımını buraya girin

  1. Kural tabanlı stil içeren “contours_with_labels” adında sanal bir katman:

    • Kural 1: “label” = 1… basit çizgi, opaklık% 0
    • Kural 2: ELSE… basit çizgi

    • ve Kural 1 için koşullu bir etiket metni:

      OLDUĞU DURUMDA etiket = 1 SONRA ELSE '' SON

    • Metin yerleştirme için bir Geometry jeneratörü ile:

      make_line (başlangıç_ noktası ($ geometri), bitiş_ noktası ($ geometri))

    • ve değişken metin boyutu için bir İfade Dizesi:

      özniteliği (get_feature ('settings', 'değişken', 'contourlabel_size'), 'değer')

ve son fakat en az değil, işte sanal katman için SQL sorgusu:

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

Bu kadar.

Bunu mümkün kılan tüm bu coşkulu insanlara çok teşekkürler!


Söylemeliyim ki, sonuçtan etkilendim. Yerleşik bir seçenek elde edene kadar (eğer varsa), bu kesinlikle en temiz yol. Kurtarmaya sanal katmanlar, yine.
Gabriel C.

Gerçekten kendimden etkilendim. Ancak, gerçekten büyük kontur katmanlarına dayanabilir mi?
christoph

1

Bu konuyu hatırlıyor musun Martin? Sorununuza bir çözüme yaklaşmak için düşünebilmemin tek yolu, kontur katmanınızı kırpılmış bir kontur katmanıyla kaplamak, bunu etiketleme için kullanmak ve çizgi rengini etiketlerin altındaki konturları maskeleyecek nötr bir şeye değiştirmek olacaktır. insan çok müdahaleci olmadan umut ediyor. N.

Sonra eklendi: bu konuya bakmak da faydalı olabilir , ikinci cevap. Belki kontür çizgilerini kesmek, belki kontürleri kırpmak için kullanılan tampon katmanını kullanarak bir cevap olabilir.


0

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

Kontur etiketleri için değişken derinlikli maskeleme üç adımdan oluşur:

1 etiketlerden açıklama oluşturma, 2 maskeleri oluşturmak için Özellik Anahat Maskeleri aracını kullanma ve maskeleri hangi katmanları maskeleyeceğini belirtmek için Gelişmiş Çizim Seçenekleri> Maskeleme ayarlarını kullanma.


Bu, nasıl uygulanabileceğini gösterir, ancak soruyu gerçekten cevaplamaz.
underdark

0

Etiketleri daha mükemmel hale getirmek için, sanal katmanın SQL sorgusunu, kontur çizgilerine paralel çalışan çizik çizgilere uyması için değiştirdim (aşağıdaki çözüme bakın):

Eski versiyon görüntü tanımını buraya girin

Yeni sürüm görüntü tanımını buraya girin

Ve işte sanal katman için yeni 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)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.