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 (він повинен мати те саме ім'я форми форми, який ви використовуєте).