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

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

    Я думаю, что if (выражение, истинное значение, ложное значение) является довольно новым; если вы используете более старую версию, вы можете использовать CASE-ELSE

  4. Измените стиль линии так, чтобы все сегменты фиксированной длины рисовались, кроме тех сегментов, где отображается метка. Поэтому используйте рендеринг на основе правил с двумя правилами

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

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

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

    Перейдите в режим редактирования и вручную выберите сегменты, в которых вы хотите отобразить значения контуров, и установите значение showLabel1 для выбранных объектов. Вы можете использовать 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
Это единственное полностью работающее решение, которое я могу себе представить. Очень больно, хотя, если есть много этикеток, я не могу себе представить, чтобы все мои карты грунтовых вод (тысячи в год) таким образом. Было бы здорово, если бы в будущем это было достигнуто с помощью стиля - так как лучше всего было бы использовать собственный шаблон линии и метку repeat + offset.
Миро
2
Просто несколько идей, чтобы облегчить задачу: чтобы выбрать несколько сегментов для рисования метки, удобно выбрать «Выбор по полигону» или «Выбор вручную». Кроме того, другим подходом было бы создание слоя линий с нулями, чтобы нарисовать линии, которые пересекают контуры, а затем сделать выбор по местоположению.
Александр Нето
7

Я использую опцию «Буфер» на вкладке «Настройка метки». (Использование кнопки надписей, а не старой опции надписей в диалоговом окне свойств слоя.) Это не стирает контурную линию, как я полагаю, вы хотите, но она делает разметку разборчивой.

SCRo
источник
4
Я никогда не думал об этом раньше, но было бы удобно, если бы вместо того, чтобы назначить цвет для буфера, вы можете применить его в качестве «выбивки» для выбранных слоев.
Scro
5
В последней версии QGIS есть прозрачные буферы, поэтому вы можете уменьшить влияние на другие части карты.
Натан Ш
1
@MAP A нокаут стирает пиксели под ним. Если бы это был вариант, в этом случае вы бы выбили контурный слой.
Scro
1
нокаут - термин esri - "маскировка" resources.arcgis.com/en/help/main/10.1/index.html#//…
май
1
@MAP - спонсор разработчик или отправить запрос на функцию и ждать благосклонности других. :)
Scro
5

Я думаю, что самое близкое, что можно получить с текущими возможностями QGIS, - это использовать эффект ореола (или фона) с цветом, полученным из таблицы, который будет основан на значении высоты и цветовой схеме, которые используются для базовой сетки. Конечно, это не будет учитывать склоны и все остальное ниже ореола на карте. Пример случайного цвета: случайный цвет для эффекта ореола этикеток с небольшим количеством кода это можно переписать как функцию для отображения цвета сетки.

Теоретически должно быть возможно использовать собственный шаблон линии и метку repeat + offset . К сожалению, нет настройки смещения метки.

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

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

Miro
источник
2

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

Короче говоря, скрипт использует два векторных слоя в качестве входных данных - аннотированный контурный слой и слой «направляющих». Последний состоит из полилиний, пересекающих контуры в нужных местах меток.

Затем сценарий работает на основе расстояния между контурами и интервала контура индекса, который должен применяться метками, добавляет значение поворота к точкам меток и, в конечном итоге, обрезает исходный слой контура для создания промежутков.

Макрофотография конечного результата.

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

К сожалению, я не могу добавить больше картинок, чтобы документировать или проиллюстрировать процесс дальше.

PS: при использовании слоев стилей, представленных в репозитории, пользователям может понадобиться «активировать» настраиваемые поля для «Поворот», «Показать метку» и «Всегда показывать» в меню меток. На некоторых установках QGIS они применяются автоматически из таблицы стилей - я пока не выяснил, чем это вызвано.

Фил Г
источник
2

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

Это очень динамичное решение позволяет нам немедленно изменять все размеры текста и положение этикеток, и даже выдерживает экспорт в PDF-вектор!

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

Для этого нам понадобятся следующие части:

  1. Векторный слой «LINESTRING» или «MULTILINESTRING», называемый «contours», с двумя полями: «fid» (Interger64 - первичный ключ), «elev» (строка)
  2. Векторный слой «LINESTRING», называемый «scratch_lines» (см. Красные линии на рисунке)
  3. Таблица без геометрии, называемая «настройки», для хранения глобального размера метки контура (это простой обходной путь, поскольку QGIS не может использовать переменные проекта в запросах SQL на данный момент): «fid» (Integer64 - первичный ключ), «переменная» (Строка), «значение» (Строка)

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

  1. Виртуальный слой, называемый то есть «contours_with_labels» со стилем на основе правил:

    • Правило 1: «метка» = 1… простая линия, непрозрачность 0%
    • Правило 2: ЕЩЕ ... простая линия

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

      СЛУЧАЙ, КОГДА этикетка = 1, ТОГДА ЭЛЕМЕНТ '' END

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

      make_line (начальная точка ($ геометрия), конечная точка ($ геометрия))

    • и строка выражения для переменного размера текста:

      атрибут (get_feature ('settings', 'variable', '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)

Вот и все.

Большое спасибо всем этим увлеченным людям, которые делают это возможным!

Christoph
источник
Должен сказать, я впечатлен результатом. Пока мы не получим встроенную опцию (если вообще когда-либо), это, безусловно, самый чистый способ. Виртуальные слои на помощь, опять же.
Габриэль С.
Я был действительно впечатлен собой. Но выдержит ли он действительно большие контурные слои?
Кристоф
И я очень рад, после тестирования, что он также работает с данными в GeoPackages! Я хотел проверить, так как он основан на Spatialite. Жаль, что я не мог голосовать не раз ...
Габриэль С.
ИМХО, это не зависит от формата файла, потому что запрос выполняется внутри QGIS. Так что должно даже работать с CSV.
Кристоф
Похоже, это не конец истории. После сегодняшнего исследования я понял, что мы можем использовать функции выражений QGIS внутри SQL-запроса виртуального уровня: gis.stackexchange.com/questions/320991/… . Так что впереди еще много чего, что ускорит маскирование меток (я думаю о масштабно-зависимых запросах или более эффективном использовании пространственных индексов).
Кристоф
1

Ты помнишь эту тему, Мартин? Единственный способ приблизиться к решению вашей проблемы - это наложить слой контура на слой обрезанного контура, использовать его для маркировки и изменить цвет линии на нейтральный, маскирующий контуры под метками, каждый надеется, не будучи слишком навязчивым. Н.

Добавлено позже: возможно, стоит посмотреть и эту ветку , второй ответ. Возможно, ответом будет разрыв линий контура, возможно, используя буферный слой, используемый для обрезания контуров?

nhopton
источник
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)
Christoph
источник
1

Небольшое дополнение, связанное с оригинальным вопросом.

Для всех тех, кто не знает о том, что мы можем использовать стилизацию "Генератор геометрии", чтобы упростить и сгладить наши контурные линии в QGIS 3.10:

гладкий (упрощенный ($ геометрия, 2), 2)

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

Christoph
источник
0

Запись в блоге ESRI: http://blogs.esri.com/esri/arcgis/2011/11/28/variable-depth-masking-contour-label-example/

Маскирование переменной глубины для контурных меток включает три этапа:

1создание аннотации на основе меток, 2 использование инструмента «Маски контура объекта» для создания масок и 3 использование параметров «Дополнительные параметры рисования»> «Маскировка», чтобы указать, какие слои маскируются.

Дженни
источник
Это показывает, как это может быть реализовано, но на самом деле это не отвечает на вопрос.
Подземье