Створення галузевих ліхтарів у QGIS?


24

Я використовую QGIS 2.18. Мені потрібно створити секторні ліхтарі для навігаційних цілей на карті.

У мене є дані про легкий сектор у вигляді полів, що дають becon_id, стартовий ступінь, кінцевий ступінь та колір у форміфайлу з понад 500 буями, маяками та маяками, які потрібно показати на карті. Для кожного маяка може бути багато рядків, кожен з яких описує один легкий сектор (наприклад, білий сектор)

Кінцевий результат повинен виглядати приблизно так: Світлі сектори в потрібних кольорах з кольором, позначеним символом у кольоровому полі (RGW), і пунктирними лініями від 100 м до 1000 м від буя / маяка / маяка.

Це, швидше за все, має бути створене як символ, що базується на правих, але, мабуть, потрібен питон?

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

Нижче наведено приклад даних формфайлу для маяка (на жаль, не вище), який має зелений сектор між 114 і 154 градусами, білий сектор між 154 і 168 градусами, червоний сектор між 168 і 237 градусами, зелений сектор між 237 і 314 градусами, білий сектор між 314 і 320 градусами, червоний сектор між 320 і 337 градусами (чомусь 0 не північ, а південь):

Приклад таблиці форм



2
Скажіть, будь ласка, можете завантажити зразок набору даних та відредагувати своє запитання, уточнивши, який саме результат ви очікуєте? На доданому зображенні я бачу лише всесвіт символів та кольорів.
mgri

1
Тут допоможуть приклади даних. Чи є у вас одна особливість на світло сектора чи одна особливість на буй? Тут може допомогти плагін Wedge Buffer, але наскільки просто це буде залежати від налаштування ваших даних.
Стівен Кей

Привіт @mgri та Стівен, я додав приклади даних і намагався зробити питання зрозумілішим :), дякую!
Бенджамін Доннер

1
@mgri рядки не є змінною, але лінії, які статично повинні бути показані як 900 м довгими лініями між легкими секторами, як на зображенні. Проектована система відліку.
Бенджамін Доннер

Відповіді:


50

EDIT Я відредагував відповідь на керування конкретними ситуаціями (за рахунок конкретних значень кута) та не відображення пунктирних ліній при визначенні кругового кута.


Я пропоную рішення, лише повторившись символіки та маркування на основі правил.

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

Крім того, це рішення працює лише в тому випадку, якщо ви вважаєте, що 0ступінь становить північ, а не південь (якщо 0це південь, то достатньо буде підсумовувати 180значення кожного разу, коли у формулах, що стосуються кутів, наприклад cos(radians(90)), стане значення "90" cos(radians(180 + 90))). Я вважав за краще це робити тільки заради того, щоб дати більш загальне рішення.


Стилізація

Ми будемо відображати точки з a Single symbolі, повторюючи один Simple Markerі три Geometry generatorсимвольні шари:

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

У подальшому поясненні я дотримуватимусь того ж порядку символів на зображенні вище.

1) Простий маркер

Я вибрав за замовчуванням чорну зірку (це простіша частина цього підручника), розмір 3 мм і ширина 0,4 мм.

2) Генератор геометрії №1

Додайте новий шар символів і виберіть Geometry generatorтип:

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

Вставте цей вираз у Expressionполе:

CASE
WHEN abs( "ALKUKULMA" - "LOPPUKULMA") < 360
THEN
make_line(
 $geometry,
 make_point(
  $x + 1000*cos(radians(90 - "ALKUKULMA")),
  $y + 1000*sin(radians(90 - "ALKUKULMA"))
  )
)
END

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

3) Генератор геометрії №2

Те саме, що вище, але на цьому кроці вам потрібно використовувати цей вираз:

CASE
WHEN abs( "ALKUKULMA" - "LOPPUKULMA") < 360
THEN
make_line(
 $geometry,
 make_point(
  $x + 1000*cos(radians(90 - "LOPPUKULMA")),
  $y + 1000*sin(radians(90 - "LOPPUKULMA"))
  )
)
END

Ми тільки що визначили першу лінію, яка вказує на точку, в якій закінчується світловий сектор. Ця лінія завдовжки 1000 м і створюється лише тоді, коли кут відкриття світлового сектора не є круглим кутом (це відбувається, щоб уникнути того, що лінія розірвала б ціле коло).

4) Геометричний генератор №3

Вставте цей вираз у Expressionполе:

CASE

WHEN abs("ALKUKULMA" - "LOPPUKULMA") <= 180 AND "ALKUKULMA" >= "LOPPUKULMA"
THEN
difference(
 boundary(
  buffer(
   $geometry, 900)
   ),
  make_polygon(
   geom_from_wkt(
    geom_to_wkt(
     make_line(
      $geometry,
      make_point($x + 2000*cos(radians(90 - "ALKUKULMA" )), $y + 2000*sin(radians((90 - "ALKUKULMA" )))),
      make_point($x + 2000*cos(radians(90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )), $y + 2000*sin(radians((90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )))),
      make_point($x + 2000*cos(radians(90 - "LOPPUKULMA")), $y + 2000*sin(radians((90 - "LOPPUKULMA")))),
      $geometry)
   )  
  )
 )
)

WHEN abs("ALKUKULMA" - "LOPPUKULMA") <= 180 AND "ALKUKULMA" <= "LOPPUKULMA"
THEN
intersection(
 boundary(
  buffer(
   $geometry, 900)
   ),
  make_polygon(
   geom_from_wkt(
    geom_to_wkt(
     make_line(
      $geometry,
      make_point($x + 2000*cos(radians(90 - "ALKUKULMA" )), $y + 2000*sin(radians((90 - "ALKUKULMA" )))),
      make_point($x + 2000*cos(radians(90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )), $y + 2000*sin(radians((90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )))),
      make_point($x + 2000*cos(radians(90 - "LOPPUKULMA")), $y + 2000*sin(radians((90 - "LOPPUKULMA")))),
      $geometry)
   )  
  )
 )
)

WHEN abs("ALKUKULMA" - "LOPPUKULMA") > 180 AND "ALKUKULMA" >= "LOPPUKULMA"
THEN
intersection(
 boundary(
  buffer(
   $geometry, 900)
   ),
  make_polygon(
   geom_from_wkt(
    geom_to_wkt(
     make_line(
      $geometry,
      make_point($x + 2000*cos(radians(90 - "ALKUKULMA" )), $y + 2000*sin(radians((90 - "ALKUKULMA" )))),
      make_point($x - 2000*cos(radians(90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )), $y - 2000*sin(radians((90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )))),
      make_point($x + 2000*cos(radians(90 - "LOPPUKULMA")), $y + 2000*sin(radians((90 - "LOPPUKULMA")))),
      $geometry)
   )  
  )
 )
)

WHEN abs("ALKUKULMA" - "LOPPUKULMA") > 180 AND "ALKUKULMA" <= "LOPPUKULMA"
THEN
difference(
 boundary(
  buffer(
   $geometry, 900)
   ),
  make_polygon(
   geom_from_wkt(
    geom_to_wkt(
     make_line(
      $geometry,
      make_point($x + 2000*cos(radians(90 - "ALKUKULMA" )), $y + 2000*sin(radians((90 - "ALKUKULMA" )))),
      make_point($x - 2000*cos(radians(90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )), $y - 2000*sin(radians((90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )))),
      make_point($x + 2000*cos(radians(90 - "LOPPUKULMA")), $y + 2000*sin(radians((90 - "LOPPUKULMA")))),
      $geometry)
   )  
  )
 )
)


END

Ми щойно визначили дугу між початковою та кінцевою точками світлового сектора (зверніть увагу, що 2000це довільне значення, тому що я намагаюся створити багатокутник для перетину з межею кола, що має радіус 900 м).

Крім того, нам потрібно встановити колір, який зберігається в "VARIS"полі. Для цього нам потрібно вказати це спеціальним виразом. Дотримуйтесь стрілки на зображенні нижче:

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

а потім введіть цей вираз після натискання на Edit...кнопку:

CASE
WHEN  "VARIS" = 'vi' THEN color_rgb(51,160,44)
WHEN "VARIS" = 'v' THEN color_rgb(255,255,255)
WHEN "VARIS" = 'p' THEN color_rgb(227,26,28)
END

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


Маркування

1) Встановлення міток

Перейдіть до Layer Properties> Labelsі, як завжди, дотримуйтесь червоних стрілок:

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

а потім введіть цей вираз:

CASE
WHEN "VARIS" = 'vi' THEN 'G'
WHEN "VARIS" = 'v' THEN 'W'
WHEN "VARIS" = 'p' THEN 'R'
END

Ми щойно визначили правило кольору, використовуючи значення, збережене в "VARIS"полі.

2) Встановлення місця розташування для міток

Виберіть Placementпараметр у Labelsменю та виберіть Offset from point.

Потім, посилаючись на зображення нижче:

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

дотримуйтесь червоної стрілки і введіть цей вираз:

CASE
WHEN "ALKUKULMA" > "LOPPUKULMA"
THEN
concat(
 -1000*cos(radians(90 - ("ALKUKULMA" + "LOPPUKULMA")/2)),
  ',',
  1000*sin(radians(90 - ("ALKUKULMA" + "LOPPUKULMA")/2))
)
WHEN "ALKUKULMA" <= "LOPPUKULMA"
THEN
concat(
 1000*cos(radians(90 - ("ALKUKULMA" + "LOPPUKULMA")/2)),
  ',',
  -1000*sin(radians(90 - ("ALKUKULMA" + "LOPPUKULMA")/2))
)
END

Потім виконайте зелену стрілку і введіть цей вираз:

CASE
WHEN "ALKUKULMA" >= "LOPPUKULMA"
THEN
180-(("ALKUKULMA" + "LOPPUKULMA")/2)
WHEN "ALKUKULMA" < "LOPPUKULMA"
THEN
- (("ALKUKULMA" + "LOPPUKULMA")/2)
END

Кінцевий результат

Якщо ви правильно виконали попередні завдання, ви зможете отримати цей результат:

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

Бонус

Оскільки мінорних параметрів було занадто багато для повного висвітлення в цій відповіді, я додав тут стиль : ви можете відкрити цей код у будь-якому текстовому редакторі та зберегти його як файл стилю QGIS Layer Style (тобто з .qmlрозширенням).

Вищеописаний стиль був створений за допомогою QGIS 2.18.4 (він повинен мати те саме ім'я форми форми, який ви використовуєте).


3
Виглядає чудово, справді показує вам потужність генератора геометрії. Чи повільно візуалізувати?
HeikkiVesanto

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

2
Питання / відповіді на кшталт цих дійсно показують, наскільки універсальним може бути QGIS!
Йосип

1
@mgri ти Майстер, фантастично гарне рішення та чудове пояснення, що передбачає багато роботи, ДЯКУЮ !!
Бенджамін Доннер

1
@mgri гора в цьому регіоні повинна бути названа на честь вас, дякую !! Я трохи перевірив, і жодних проблем із вашими доданими рішеннями не знайдено :)!
Бенджамін Доннер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.