Wie kann ich Konturlinien unter Höhenbeschriftungen unterbrechen (anstatt Beschriftungspuffer zu verwenden)?

32

Gibt es eine Möglichkeit, eine Konturlinie unter einer Höhenbeschriftung zu unterbrechen?

Bildbeschreibung hier eingeben

KARTE
quelle
ArcGIS? QGIS? Brauch?
Ragi Yaser Burhum
1
Ich benutze QGIS für die Konturbeschriftung
MAP
Würden Sie eine Antwort akzeptieren, die PostGIS erfordert?
Scro
3
leider: nein :) Aber gibt es eine Möglichkeit, das Problem mit PostGIS zu lösen?
KARTE

Antworten:

22

Ja machbar Normalerweise würde ich einen teilweise transparenten Puffer vorschlagen, aber ich sehe, warum Sie dies kartografisch tun möchten.

Dies kann langsam sein, und Sie müssen manuell entscheiden, wohin die Etiketten gehen sollen - aber kartografisch gesehen ist das keine schlechte Sache!

Hier ist ein Screenshot ...

Wie Sie sehen, keine Puffer. Das Raster darunter ist nicht betroffen. Ich habe dünnere Konturzwischenlinien eingefügt und sie so gestaltet, dass sie nur angezeigt werden, wenn ELEV% 50 <> 0

Beispiel für unterbrochene Höhenlinien

Ich habe dies in QGIS 2.12 getan ... Ihr Kilometerstand kann von früheren Versionen abweichen.

Ich gehe davon aus, dass Sie hier ein "ELEV" -Feld auf jeder Konturlinie haben.

Segmentieren Sie die Konturlinien

  1. Verwenden Sie die Verarbeitung und den GRASS-Algorithmus v.split.length , um Ihre Konturen in gleich lange Segmente aufzuteilen. Sie müssen eine Länge wählen, die der Größe Ihres Etiketts in Karteneinheiten entspricht, vorausgesetzt, Sie verwenden Meter. Hier habe ich 200m benutzt.

    Seien Sie vorsichtig damit, da Ihre Datei dadurch sehr viel größer wird (beachten Sie, dass die Funktion im Screenshot zählt).

    Um dies zu umgehen, möchten Sie möglicherweise nur die Konturlinien generieren, die Sie formatieren möchten (z. B. alle 50 oder 100 Meter), um zu vermeiden, dass alle Zwischenkonturlinien verarbeitet werden.

  2. Fügen Sie dieser Ebene ein 1-stelliges Ganzzahlfeld mit dem Namen showLabel hinzu . Standardmäßig 0 oder NULL.

  3. Ändern Sie die Beschriftung so, dass sie nur in einem Segment angezeigt wird, in dem dieses Feld auf 1 gesetzt ist. Verwenden Sie dies für den Beschriftungstextausdruck ...

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

    Ich denke, wenn (Ausdruck, wahrer Wert, falscher Wert) ziemlich neu ist; Wenn Sie eine ältere Version verwenden, können Sie CASE-ELSE verwenden

  4. Ändern Sie den Linienstil so, dass alle Segmente mit fester Länge gezeichnet werden, mit Ausnahme der Segmente, in denen die Bezeichnung angezeigt wird. Verwenden Sie daher das regelbasierte Rendern mit zwei Regeln

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

    Jetzt werden standardmäßig alle Konturen angezeigt, jedoch keine Beschriftungen.

    Bearbeiten Sie Segmente manuell, in denen Beschriftungen angezeigt werden sollen

    Wechseln Sie in den Bearbeitungsmodus und wählen Sie manuell die Segmente aus, in denen die Konturwerte angezeigt werden sollen. Setzen Sie den Wert showLabelfür die ausgewählten Features auf 1. Sie können Ctrl+ select (unter Ubuntu / Win, Cmd+ Ctrl+ Click / on Mac?) Verwenden , um Segmente mehrfach auszuwählen, um die Dinge zu beschleunigen.

    Dies sollte nun die Konturen "beschneiden", an denen die Beschriftungen angezeigt werden sollen, und die Beschriftungen werden in den Lücken angezeigt.

In diesem Fall lauteten meine Beschriftungseinstellungen:

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

Hoffentlich hilft das!

Steven Kay
quelle
5
Dies ist die einzige voll funktionsfähige Lösung, die ich mir vorstellen kann. Sehr schmerzhaft, wenn es viele Etiketten gibt, kann ich mir nicht vorstellen, alle meine Grundwasserkopfkarten (Tausende pro Jahr) auf diese Weise zu erstellen. Wäre großartig, wenn dies in Zukunft durch Stil erreicht werden könnte - am besten durch benutzerdefiniertes Linienmuster und Etikettenwiederholung + Versatz.
Miro
2
Nur ein paar Ideen, um die Aufgabe zu vereinfachen: Um die mehreren Segmente zum Zeichnen der Beschriftung auszuwählen, kann Auswahl per Polygon oder Auswahl per Freihand nützlich sein. Ein weiterer Ansatz wäre, eine Kratzlinienebene zu erstellen, um Linien zu zeichnen, die die Konturen abfangen, und dann eine Auswahl nach Position vorzunehmen.
Alexandre Neto
7

Ich verwende die Option "Puffer" auf der Registerkarte "Etiketteneinstellung". (Verwenden Sie die Schaltfläche "Beschriftungen", nicht die Option "Alte Beschriftungen" im Dialogfeld "Ebeneneigenschaften".) Dadurch wird die Konturlinie nicht wie gewünscht verwischt, aber die Beschriftung wird lesbar.

Scro
quelle
4
Ich habe noch nie darüber nachgedacht, aber es wäre praktisch, wenn Sie dem Puffer keine Farbe zuweisen, sondern ihn als Aussparung auf ausgewählte Ebenen anwenden könnten.
Scro
4
Die neueste Version von QGIS verfügt über transparente Puffer, mit denen Sie die Auswirkungen auf andere Teile der Karte verringern können.
Nathan W
1
@MAP Ein Knockout löscht die Pixel darunter. Wenn dies eine Option wäre, würden Sie in diesem Fall die Konturebene aussparen.
Scro
1
knockout - der esri-begriff "maskiert" resources.arcgis.com/de/help/main/10.1/index.html#//…
mike
1
@MAP - Sponsern Sie einen Entwickler oder senden Sie eine Feature-Anfrage und warten Sie auf das Wohlwollen anderer. :)
Scro
5

Ich denke, das Beste, was mit den aktuellen QGIS-Fähigkeiten erreicht werden kann, ist die Verwendung des Halo- (oder Hintergrund-) Effekts mit Farben aus der Tabelle, die auf dem Höhenwert und dem Farbschema basieren, die für das zugrunde liegende Raster verwendet werden. Natürlich wäre dies nicht berücksichtigt Schummerungs und alles andere unter dem Halo in der Karte. Beispiel für zufällige Farben: zufällige Farbe für den Halo-Effekt von Etiketten Mit ein bisschen Code könnte dies als Funktion zur Darstellung der Rasterfarbe umgeschrieben werden.

Theoretisch sollte es möglich sein, benutzerdefiniertes Linienmuster und Label Repeat + Offset zu verwenden . Leider gibt es keine Einstellung für den Etikettenversatz.

  • Nach einigen Tests ist es unmöglich, QGIS zu zwingen, die Beschriftungen genau in Intervallen und nirgendwo anders zu platzieren (+ fehlender Startoffset)
  • Es ist nicht möglich, ein benutzerdefiniertes Linienmuster mit einem Abstand von 0 mm zu erstellen, um einen Startversatz von 20 Linien - 10 Leerzeichen - 70 Linien - 0 Leerzeichen zu erhalten. Die Beschriftung wird also alle 100 mm mit einem Abstand von 30 mm am Anfang platziert die Mitte von jedem 10mm Loch.

Bildbeschreibung hier eingeben

Miro
quelle
2

Nachdem ich kürzlich auf dasselbe Problem gestoßen bin, habe ich ein QGIS-Python-Skript zusammengestellt, um das schwere Heben durchzuführen. Das Skript mit einigen Testdaten (Großbritannien), Readme-Datei (Handbuch) und verwendeten Stylesheets finden Sie unter https://github.com/pjgeng/Contour-Labels

Kurz gesagt, das Skript verwendet zwei Vektorebenen als Eingabe - die mit Anmerkungen versehene Konturenebene und eine "Hilfslinien" -Ebene. Letzteres besteht aus Polylinien, die die Konturen an den gewünschten Etikettenpositionen schneiden.

Das Skript erarbeitet dann basierend auf dem Abstand zwischen Konturen und dem Indexkonturintervall, auf das die Beschriftungen angewendet werden sollen, fügt den Beschriftungspunkten einen Rotationswert hinzu und schneidet schließlich die ursprüngliche Konturebene ab, um die Lücken zu erzeugen.

Nahaufnahme des Endergebnisses.

Der Ansatz funktioniert besonders gut, wenn der Benutzer Konturenkarten in unterschiedlichen Intervallen im selben Bereich erstellen muss (dh die Hilfslinien ändern sich nicht). Ein Nachteil ist die Unfähigkeit, die Etikettenposition zu ändern, wenn das Skript beendet ist. Hierzu müsste der Benutzer die Hilfslinien anpassen und das Skript erneut mit der ursprünglichen Eingabe ausführen. Früher habe ich viel mit Puffern um Etiketten gearbeitet, um den unterbrochenen Effekt zu erzeugen, aber dies stellte sich bei vektordatengesteuerten Karten als ästhetisch unangenehm heraus.

Leider kann ich zur Zeit keine Bilder mehr hinzufügen, um den Vorgang weiter zu dokumentieren oder zu veranschaulichen.

PS: Wenn Sie die im Repository bereitgestellten Stilebenen verwenden, müssen Sie möglicherweise die benutzerdefinierten Felder für "Drehung", "Beschriftung anzeigen" und "Immer anzeigen" im Beschriftungsmenü "aktivieren". Bei einigen Installationen von QGIS werden diese automatisch aus dem Stylesheet übernommen - ich habe noch nicht herausgefunden, woran das liegt.

Phil G
quelle
1

Erinnerst du dich an diesen Thread Martin? Ich kann mir nur vorstellen, einer Lösung für Ihr Problem nahe zu kommen, indem ich Ihre Konturebene mit einer abgeschnittenen Konturebene überschreibe, diese zum Beschriften verwende und die Linienfarbe in etwas Neutrales ändere, das die Konturen unter den Beschriftungen maskiert. man hofft, ohne zu aufdringlich zu sein. N.

Später hinzugefügt: Es könnte sich lohnen, sich auch diesen Thread anzuschauen, die zweite Antwort. Vielleicht könnte das Brechen der Konturlinien eine Antwort sein, vielleicht unter Verwendung der Pufferebene, die zum Ausschneiden der Konturen verwendet wird?

nhopton
quelle
1

Hier ist eine weitere Lösung für das Problem der QGIS-Konturetiketten-Maskierung, bei der ich die Spatialite-Funktionalität von QGIS (derzeit QGIS 3.x) zusammen mit einem Geometriegenerator für die Etikettenplatzierung nutze.

Diese sehr dynamische Lösung ermöglicht es uns, alle Beschriftungstextgrößen und Beschriftungspositionen sofort zu ändern und sogar einen PDF-Vektorexport zu überstehen!

Bildbeschreibung hier eingebenBildbeschreibung hier eingebenBildbeschreibung hier eingebenBildbeschreibung hier eingeben

Um dies zu ermöglichen, benötigen wir folgende Teile:

  1. Eine Vektorebene "LINESTRING" oder "MULTILINESTRING" mit der Bezeichnung "Konturen" und zwei Feldern: "fid" (Interger64 - Primärschlüssel), "elev" (Zeichenfolge)
  2. Eine Vektorebene "LINESTRING" mit dem Namen "scratch_lines" (siehe rote Linien im Bild)
  3. Eine geometrielose Tabelle mit dem Namen "settings" zum Speichern der globalen Konturbeschriftungsgröße (dies ist eine einfache Problemumgehung, da QGIS derzeit keine Projektvariablen in SQL-Abfragen verwenden kann): "fid" (Integer64 - Primärschlüssel), "variable" (String), "Wert" (String)

Bildbeschreibung hier eingeben

  1. Eine virtuelle Ebene mit dem Namen "contours_with_labels" mit regelbasiertem Stil:

    • Regel 1: “label” = 1… einfache Linie, Deckkraft 0%
    • Regel 2: ELSE… einfache Linie

    • und einen bedingten Etikettentext für Regel 1:

      CASE WHEN label = 1 THEN elev ELSE '' END

    • mit einem Geometrie-Generator zur Textplatzierung:

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

    • und eine Ausdruckszeichenfolge für die variable Textgröße:

      attribute (get_feature ('settings', 'variable', 'contourlabel_size'), 'value')

Und zu guter Letzt folgt hier die SQL-Abfrage für die virtuelle Ebene:

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

Das ist es.

Vielen Dank an alle diese begeisterten Menschen, die dies möglich machen!

Christoph
quelle
0

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

Die Maskierung mit variabler Tiefe für Konturetiketten umfasst drei Schritte:

1Erstellen von Anmerkungen aus den Beschriftungen, 2Erstellen von Masken mit dem Werkzeug "Feature-Gliederungsmasken" und 3Erstellen von Masken mit den Einstellungen "Erweiterte Zeichenoptionen"> "Maskieren".

Jenny
quelle
Dies zeigt, wie es implementiert werden könnte, aber es beantwortet die Frage nicht wirklich.
underdark