Символ лінії зигзагу в QGIS


18

Я шукаю символ зигзагоподібної лінії в QGIS. Чи є простий спосіб зробити це, чого мені не вистачає? Я спробував створити маркерну лінію за допомогою простого маркера трикутника (^) і відкоригувавши розмір маркера та інтервал розміщення маркера, доки трейлінг не торкнувся один одного і не виявилося зробити гарну зигзагоподібну лінію. Це працює для прямих, але навколо кривих є проміжки між трикутниками, оскільки трикутники насправді не з'єднані. Чи може бути спосіб з'єднати маркери разом? Або інший шлях для цього? Буду дуже вдячний за будь-які пропозиції! (з використанням QGIS 2.4.0) Моя спроба зігзагоподібної лінії

Відповіді:


11

Здається, немає можливості просто символізувати лінію як зигзаг: на жаль, вам доведеться змінити основні дані.

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

Ось сценарій Python, який робить це, приймаючи відповідь NathanW на те, як я можу створювати випадкові точки вздовж полілінії в QGIS? як вихідний пункт. Збережіть фрагмент коду у файл, який називається zigzag.pyу вашому ~/.qgis/pythonкаталозі (або {User Directory}\.qgis\python\в Windows), а потім імпортуйте його в консоль QGIS Python, ввівши import zigzag. Тоді ви можете вибрати одну або кілька ліній, які ви хочете зігзагіфікувати, і набрати zigzag.createZigzag(<wavelength>, <amplitude>)в консолі QGIS Python, де <wavelength>і <amplitude>є "довжина" і "ширина" сегментів зигзагу, в одиницях карти.

Ось приклад:

Як бачимо, зигзаги не дуже приємні біля кутів оригінальної лінії, але принаймні на лінії зигзагу немає жодних перерв.

Якщо ви використовуєте пропозицію Джеймса Конклінга, щоб спочатку згладити лінію, використовуючи алгоритм Чайкена, результат виходить набагато приємнішим:


Ось сценарій:

from qgis.utils import iface
from qgis.core import *
import numpy as np
from cmath import rect, phase


# Function for calculating the mean of two angles.
# Based on http://rosettacode.org/wiki/Averages/Mean_angle#Python
def meanAngle(a1, a2):
    return phase((rect(1, a1) + rect(1, a2)) / 2.0)


def createZigzag(wavelength, amplitude):
    # Create a new memory layer to store the zigzag line.
    vl = QgsVectorLayer("LineString", "Zigzag", "memory")
    pr = vl.dataProvider()

    # For each selected object in the current layer
    layer = iface.mapCanvas().currentLayer()
    for feature in layer.selectedFeatures():
        geom = feature.geometry()

        # Number of zigzag segments
        length = geom.length()
        segments = np.round(length / wavelength)

        # Find equally spaced points that approximate the line
        points = [geom.interpolate(distance).asPoint() for
            distance in np.linspace(0, length, segments)]

        # Calculate the azimuths of the approximating line segments
        azimuths = np.radians(
            [points[i].azimuth(points[i + 1]) for i in range(len(points) - 1)])

        # Average consecutive azimuths and rotate 90 deg counterclockwise
        zigzagazimuths = [azimuths[0] - np.pi / 2]
        zigzagazimuths.extend([meanAngle(azimuths[i],
            azimuths[i - 1]) - np.pi / 2 for i in range(len(points) - 1)]
        )
        zigzagazimuths.append(azimuths[-1] - np.pi / 2)

        # Offset the points along the zigzagazimuths
        zigzagpoints = []
        for i in range(len(points)):
            # Alternate the sign
            dst = amplitude * (1 - 2 * np.mod(i, 2))
            zigzagpoints.append(
                QgsPoint(points[i][0] + np.sin(zigzagazimuths[i]) * dst,
                    points[i][1] + np.cos(zigzagazimuths[i]) * dst
                )
            )

        # Create new feature from the list of zigzag points
        fet = QgsFeature()
        fet.setGeometry(QgsGeometry.fromPolyline(zigzagpoints))

        pr.addFeatures([fet])
        vl.updateExtents()

    QgsMapLayerRegistry.instance().addMapLayer(vl)

Видатне рішення! Залишилося моє питання - чи можна цей алгоритм застосовувати на полілініях.
Габор Фаркас

1
@GaborFarkas: У прикладі використовується полілінія. Ви, мабуть, маєте на увазі шар, що містить кілька суміжних поліліній (багатополіліній)? Це також працює.
Джейк

3

Я намагався це робити раніше і не мав великої долі.

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

повторний символ маркера в qGIS

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

Щоб повністю усунути прогалини і перекриття, кожен квадрат символів повинен бути перероблений у вигляді ромба різної величини - подібно до того, як камені на арці скошуються так, щоб відповідати кривій. Наскільки я знаю, неможливо імітувати щось подібне. Але ви можете зменшити спотворення, ущільнюючи і розгладжуючи геометрію лінії, щоб зміна кута була менш екстремальною. Generalizer плагін може допомогти з цим (спробуйте використовувати його з допомогою алгоритму Чайка в).

символ згладженого маркера повторювача в qGIS

Також допоможе розбиття вашого символу на менші сегменти та розміщення кожного підряд, щоб знову зменшити кут між кожним наступним маркером. Наприклад, розбийте свій Vсимвол на a \і a /, завантажте як на маркерну лінію, так і на кожну, встановіть зсув x, рівний половині їх ширини, позитивний для одного та мінус для іншого.

Нарешті, трохи товстіший штрих символів із закругленими кінцями допоможе замаскувати незначне спотворення.

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

Редагувати:

інша думка: перебіг одного символу до іншого, викликаний обертанням символу по кривій, найбільший у верхній / нижній частині символу, але менш виражений посередині. Отже шаблон, який починається і закінчується в центрі символів, матиме менші прогалини, ніж візерунок, який починається / закінчується вгорі / внизу. Напр

зигзаг

... все-таки хак - все ще не дурний


1

Я не думаю, що це особливість QGIS. Однак я б спробував зробити це так:

  1. зробіть дві копії шару, використовуючи плагін інструмента Affine. Один з шарів з дещо більшим масштабом і один з трохи меншим масштабом.

  2. Ущільнити геометрію шарів. Це означає додати більше вузлів.

  3. Перейдіть до таблиці атрибутів та назвіть кожен вузол функції, відповідно, 1,2,3, ... в одному шарі та 1b, 2b, 3b, ... у другому шарі.

  4. об'єднати обидва шари та сортувати шар атрибутів -> це повинно дати вам зигзагоподібну лінію.

Можливо, це спрацює.


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