Як перервати лінії контуру під мітками висоти (замість використання буферів міток)?


32

Чи є спосіб перервати лінію контуру під міткою висоти?

введіть тут опис зображення


ArcGIS? QGIS? На замовлення?
Рагі Ясер Бурхум

1
Я використовую qgis для контурного маркування
MAP

Чи приймете ви відповідь, що вимагає PostGIS?
Scro

3
прикро: ні :) Але чи є спосіб вирішити проблему з PostGIS?
КАРТА

Відповіді:


22

Так, виконується. Зазвичай я пропоную частково прозорий буфер, але я бачу, чому ви хочете робити це картографічно.

Це може бути повільним, і вам потрібно вручну вирішити, куди потрібно ходити етикетки - але картографічно кажучи, це не погано!

Ось скріншот ...

Як бачите, буферів немає. Растер під ним не впливає. Я включив більш тонкі проміжні контурні лінії та накреслив їх, щоб вони відображалися лише тоді, коли ELEV% 50 <> 0

приклад перерваних контурних ліній

Я робив це в QGIS 2.12 ... ваш пробіг може відрізнятися від більш ранніх версій.

Я припускаю, що у вас є поле "ELEV" на кожній лінії контуру.

Розчленуйте контурні лінії

  1. Використовуйте обробку та алгоритм GRASS v.split.length, щоб розділити контури на сегменти однакової довжини. Вам потрібно вибрати довжину, яка буде наближатися до розміру вашої мітки в одиницях карти, припускаючи, що ви використовуєте метри. Тут я використав 200м.

    Будьте обережні з цим, оскільки це зробить ваш файл набагато, значно більшим (зверніть увагу на те, що функція зараховується на скріншоті).

    Щоб обійти це, ви, можливо, захочете генерувати лише ті контури ліній, які ви хочете стилювати (наприклад, кожні 50 або 100 метрів), щоб уникнути обробки всіх проміжних контурних ліній.

  2. До цього шару додайте одноцифрове ціле поле під назвою showLabel . За замовчуванням 0 або NULL.

  3. Змініть мітку, щоб вона відображалася лише на сегменті, на якому для цього поля встановлено значення 1. Використовуйте це для виразу тексту мітки ...

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

    Я думаю, якщо (вираз, справжнє значення, хибне значення) є досить новим; якщо використовується більш стара версія, ви можете використовувати CASE-ELSE

  4. Змініть стиль лінії, щоб усі сегменти фіксованої довжини були намальовані, крім тих сегментів, де відображається мітка. Тому використовуйте відображення на основі правил з двома правилами

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

    Тепер всі контури будуть показані за замовчуванням, але ніяких міток.

    Вручну редагуйте сегменти, де ви хочете показувати мітки

    Перейдіть у режим редагування та вручну виберіть сегменти, де потрібно відобразити контурні значення, та встановіть значення showLabelдля 1 для вибраних функцій. Ви можете використовувати Ctrl+ select (на Ubuntu / Win, Cmd+ Ctrl+ Click / на Mac?) Для вибору декількох сегментів для прискорення роботи.

    Тепер він повинен "зафіксувати" контури там, де ви хочете показувати мітки, а мітки відображатимуться в проміжках.

У цьому випадку моїми налаштуваннями міток були:

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

Сподіваюся, що це допомагає!


5
Це єдине повноцінне рішення, яке я можу собі уявити. Дуже болісно, ​​хоча якщо є багато ярликів, я не можу уявити, як я роблю всі карти своїх підземних вод (тисячі на рік) таким чином. Було б чудово, якщо в майбутньому це можна досягти за допомогою стилю - як найкращий буде власний шаблон лінії та повторення мітки + зміщення.
Миро

2
Лише кілька ідей для полегшення завдання: Щоб вибрати кілька сегментів, щоб намалювати етикетку, може бути зручно вибрати Select by Polygon або Select by Freehand. Крім того, ще одним підходом буде створення шару ліній подряпини, щоб намалювати лінії, що перетинають контури, а потім зробити Вибір за місцем розташування.
Олександр Нето

7

Я використовую опцію "Буфер" на вкладці "Налаштування мітки". (Використовуючи кнопку міток, а не стару опцію міток у діалоговому вікні властивостей шару.) Це не стирає лінію контуру, як я думаю, ви хочете зробити, але це робить мітку розбірливою.


4
Я ніколи про це не думав, але було б зручно, якби замість того, щоб призначити колір для буфера, можна було застосувати його як «нокаут» до вибраних шарів.
Scro

5
В останній версії QGIS є прозорі буфери, щоб ви могли зменшити вплив на інші частини карти.
Nathan W

1
@MAP Нокаутом стирає пікселі під ним. Якби це був варіант, у цьому випадку ви вирішите вибити контурний шар.
Scro

1
нокаут - термін есрі - "маскування" ресурсів.arcgis.com/
Майк

1
@MAP - спонсоруйте розробника або надішліть запит на функцію та зачекайте на доброзичливість інших. :)
Scro

5

Я думаю, що найбільш близьким для сучасних здібностей QGIS є використання гало (або фонового) ефекту з кольором, виділеним із таблиці, який базуватиметься на значенні висоти та кольоровій гамі, як і для базової сітки. Звичайно, це не враховувало б пагорб і все інше нижче ореолу на карті. Випадковий кольоровий приклад: випадковий колір для ореолу ефекту міток з деяким бітом коду це може бути переписане як функція для відображення кольору сітки.

Теоретично слід використовувати можливість користувацького шаблону рядка та повторення мітки + зміщення . На жаль, немає налаштування зміщення мітки.

  • після деяких тестувань неможливо змусити QGIS бути суворими з розміщенням міток у точному інтервалі і ніде більше (+ відсутніх стартових зрушень все одно)
  • неможливо створити нестандартний шаблон лінії з нульовим мм, щоб пробіл мав стартове зміщення, наприклад, 20 рядків - 10 місця - 70 рядків - 0 пробілів - тому мітка розміщуватиметься кожні 100 мм із зміщенням 30 мм на початку - значення мітки було б у середина кожного 10-мм отвору.

введіть тут опис зображення


2

Нещодавно після того, як зіткнувся з тією ж проблемою, я склав сценарій QGIS Python, щоб здійснити важкий підйом. Сценарій, що включає деякі тестові дані (Великобританія), Readme (керівництво) та використовувані таблиці стилів, можна знайти на веб- сайті https://github.com/pjgeng/Contour-Labels

Коротше кажучи, сценарій використовує два векторних шари як вхідний - конспектований контурний шар та шар "напрямні". Остання складається з поліліній, що перетинають контури в потрібних місцях міток.

Потім сценарій працює на основі відстані між контурами та інтервалом контуру індексу, які мітки слід застосувати, додає значення повороту до міток міток і врешті-решт відсікає початковий контурний шар, щоб створити прогалини.

Крупним планом кінцевого результату.

Підхід особливо добре працює, якщо користувачеві необхідно створити контурні карти з різними інтервалами в одній області (тобто напрямні не змінюються). Недолік - це неможливість змінити позицію мітки після завершення сценарію. Для цього користувачеві доведеться коригувати напрямні та повторно виконувати скрипт на оригінальному введенні. Раніше я багато працював з буферами навколо міток, щоб створити ефект переривання, але це виявилося естетично неприємно на картах з векторними даними.

На жаль, наразі не можу додати більше фотографій, щоб подальше документувати чи ілюструвати процес.

PS: Якщо використовуються шари стилів, надані у сховищі, користувачам може знадобитися "активувати" спеціальні поля для "Поворот", "Показати мітку" та "Завжди показувати" в меню маркування. На деяких установках QGIS вони застосовуються автоматично з таблиці стилів - я ще не з'ясував, що це викликає.


2

Ось ще одне рішення для проблеми маскування контурних ярликів QGIS, де я використовую функціонал просторового простору QGIS (зараз QGIS 3.x) разом з генератором геометрії для розміщення етикетки.

Це дуже динамічне рішення дозволяє нам негайно змінювати всі розміри тексту міток та позиції етикетки, і навіть переживає експорт векторних PDF-файлів!

введіть тут опис зображеннявведіть тут опис зображеннявведіть тут опис зображеннявведіть тут опис зображення

Для цього нам потрібні такі частини:

  1. Векторний шар "LINESTRING" або "MULTILINESTRING", який називається "контури", має 2 поля: "fid" (Interger64 - первинний ключ), "elev" (String)
  2. Векторний шар "LINESTRING" під назвою "scratch_lines" (див. Червоні лінії на малюнку)
  3. Таблиця без геометрії під назвою "Налаштування" для зберігання глобального розміру контурної мітки (це просте вирішення, оскільки QGIS досі не може використовувати змінні Project у SQL-запитах): "fid" (Integer64 - первинний ключ), "змінний" (Рядок), "значення" (Рядок)

введіть тут опис зображення

  1. Віртуальний шар, який називається "contours_with_labels" з укладкою на основі правил:

    • Правило 1: "label" = 1… простий рядок, непрозорість 0%
    • Правило 2: ELSE… простий рядок

    • і умовний текст етикетки для правила 1:

      CASE WHEN label = 1 THEN elev ELSE '' END

    • з генератором геометрії для розміщення тексту:

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

    • і рядок виразів для змінного розміру тексту:

      атрибут (get_feature ('настройки', 'змінна', '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)

Це воно.

Велике спасибі всім цим захопливим людям, які роблять це можливим!


Треба сказати, я вражений результатом. Поки ми не отримаємо вбудований варіант (якщо і є), це, безумовно, найчистіший спосіб. Знову віртуальні шари на допомогу.
Габріель К.

Я справді був вражений собою. Але чи може вона витримувати дійсно великі контурні шари?
Крістоф

І я дуже радий після тестування, що він також працює з даними в GeoPackages! Я хотів перевірити, оскільки він заснований на Spatialite. Бажаю, щоб я міг проголосувати не раз ...
Габріель К.

IMHO, він не залежить від будь-якого файлового формату, оскільки запит працює всередині QGIS. Тож навіть слід працювати з CSV.
Крістоф

Схоже, це ще не кінець історії. Після сьогоднішнього дослідження я зрозумів, що ми можемо використовувати функції вираження QGIS всередині запиту віртуального рівня SQL: gis.stackexchange.com/questions/320991/… . Тож чекає ще багато, що прискорить маскування міток (я думаю про запити, що залежать від масштабів, або краще використовувати просторові індекси).
Крістоф

1

Ви пам’ятаєте цю нитку Мартіне? Єдиний спосіб, який я можу придумати, щоб наблизитись до вирішення вашої проблеми, це накласти ваш контурний шар обрізаним шаром контуру, використовувати це для маркування та змінити колір лінії на щось нейтральне, що маскувало б контури під мітками, можна сподіватися, не надто нав'язливо. Н.

Додано пізніше: можливо, варто також переглянути цю тему , друга відповідь. Можливо, розрив контурних ліній може бути відповіддю, можливо, використовуючи буферний шар, який використовується для обрізання контурів?


1

Щоб зробити мітки більш досконалими, я змінив 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)

1

Невеликий додаток, пов’язаний із початковим запитанням.

Для всіх тих, хто не знає про те, що ми можемо використовувати "Генератор геометрії", щоб спростити і згладити наші контурні лінії в QGIS 3.10:

гладкий (спростити ($ геометрія, 2), 2)

введіть тут опис зображення


0

Запис у блозі ESRI: http://blogs.esri.com/esri/arcgis/2011/11/28/variable-depth-masking-contour-label-example/

Маскування змінної глибини для контурних міток включає три етапи:

1створення анотацій із міток, 2використання інструмента "Маски контурних можливостей" для створення масок і 3використання параметрів "Додаткові параметри малювання"> "Маскування", щоб визначити, які шари маски будуть маскуватися.


Це показує, як це можна було б реалізувати, але насправді це не відповідає на питання.
нижній план
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.