Zick-Zack-Liniensymbol in QGIS


18

Ich suche nach einem Zick-Zack-Liniensymbol in QGIS. Gibt es vielleicht einen einfachen Weg, dies zu tun, den ich vermisse? Ich habe versucht, eine Markierungslinie mit einem einfachen Dreieck-Marker (^) zu erstellen und die Größe des Markers und das Marker-Platzierungsintervall anzupassen, bis sich die Traingles berührten und eine schöne Zick-Zack-Linie zu bilden schienen. Dies funktioniert für gerade Linien, aber um Kurven gibt es Lücken zwischen den Dreiecken, da die Dreiecke eigentlich nicht verbunden sind. Gibt es vielleicht eine Möglichkeit, die Marker miteinander zu verbinden? Oder ein anderer Weg, dies zu tun? Für Anregungen wäre ich sehr dankbar! (mit QGIS 2.4.0) Mein Versuch einer Zick-Zack-Linie

Antworten:


11

Es scheint, als gäbe es keine Möglichkeit, die Linie nur als Zickzack zu symbolisieren: Leider müssen Sie die zugrunde liegenden Daten ändern.

Sie können eine einigermaßen gute Zick-Zack-Linie erhalten, indem Sie zuerst die ursprüngliche Linie in viele äquidistante Liniensegmente aufteilen und dann jeden zweiten Punkt um einen festen Betrag versetzen.

Hier ist ein Python-Skript, das dies ausführt und die Antwort von NathanW auf Wie kann ich in QGIS zufällige Punkte entlang einer Polylinie erstellen? als Ausgangspunkt. Speichern Sie den Codeabschnitt in einer Datei, die zigzag.pyin Ihrem ~/.qgis/pythonVerzeichnis (oder {User Directory}\.qgis\python\unter Windows) aufgerufen wird , und importieren Sie ihn dann in die QGIS Python-Konsole, indem Sie Folgendes eingeben import zigzag. Dann können Sie eine oder mehrere Zeilen auswählen , die Sie zigzagify möchten, und geben Sie zigzag.createZigzag(<wavelength>, <amplitude>)in der QGIS Python - Konsole, wo <wavelength>und <amplitude>sind die „Länge“ und „Breite“ der Zick - Zack - Segmente, in Karteneinheiten.

Hier ist ein Beispiel:

Wie Sie sehen können, sind die Zickzacklinien in der Nähe der Ecken der ursprünglichen Linie nicht sehr schön, aber zumindest hat die Zickzacklinie keine Unterbrechungen.

Wenn Sie James Conklings Vorschlag verwenden, die Linie zuerst mit Chaikens Algorithmus zu glätten, wird das Ergebnis viel schöner:


Hier ist das Skript:

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)

Hervorragende Lösung! Meine einzige Frage ist, ob dieser Algorithmus auf Polylinien angewendet werden kann.
Gabor Farkas

1
@GaborFarkas: Im Beispiel wird eine Polylinie verwendet. Meinen Sie vielleicht eine Ebene mit mehreren disjunkten Polylinien (eine Mehrfachpolylinie)? Das funktioniert auch.
Jake

3

Ich habe es schon früher versucht und habe nicht viel Glück gehabt.

qGIS platziert wiederholte Symbole auf einer Linie basierend auf einem Referenzpunkt (standardmäßig die Mitte, obwohl Sie sie auf oben / Mitte / unten x links / Mitte / rechts einstellen können) und dreht dieses Symbol basierend auf der Neigung der Linie um dieser Punkt. Auf einer geraden Linie, bei der sich die Neigung nicht von einer Symbolposition zur nächsten ändert, wird jedes Symbol perfekt mit dem vorherigen ausgerichtet. In einer Kurve stimmt jedoch kein Punkt auf einem Symbol perfekt mit dem entsprechenden Punkt auf dem nächsten Symbol überein.

wiederholtes Markersymbol in qGIS

Wenn also die rote Linie die Linie selbst ist, führt das Wiederholen eines Symbols entlang dieser Linie zu Lücken zwischen Symbolen entlang der Außenseite einer Kurve und zu Überlappungen innerhalb einer Kurve.

Um die Lücken und Überlappungen vollständig zu beseitigen, müsste jedes Symbolquadrat in eine Raute unterschiedlicher Größe umgewandelt werden - ähnlich wie Steine ​​auf einem Bogen abgeschrägt werden, um sich der Kurve anzupassen. Soweit ich weiß, ist es nicht möglich, so etwas zu simulieren. Sie können die Verzerrung jedoch verringern, indem Sie die Liniengeometrie verdichten und glätten, sodass die Winkeländerung weniger extrem ist. Das Generalizer-Plugin kann dabei helfen (versuchen Sie es mit Chaikens Algorithmus).

geglättetes Repeater-Markersymbol in qGIS

Außerdem hilft es, wenn Sie Ihr Symbol in kleinere Segmente aufteilen und diese nacheinander platzieren, sodass Sie den Winkel zwischen den einzelnen nachfolgenden Markierungen wieder verringern. ZB brechen Sie Ihr VSymbol in ein \und ein /, laden Sie beide auf die Markierungslinie und setzen Sie für jedes einen x-Versatz, der der Hälfte ihrer Breite entspricht, positiv für das eine und negativ für das andere.

Schließlich würde ein etwas dickerer Symbolstrich mit abgerundeten Enden helfen, die leichte Verzerrung zu maskieren.

Dies ist immer noch ein bisschen hacken - würde gerne hören, wenn jemand einen zuverlässigeren Ansatz hat.

Bearbeiten:

Ein weiterer Gedanke: Die durch die Drehung des Symbols entlang der Kurve verursachte Fehlausrichtung von einem Symbol zum anderen ist am oberen / unteren Rand des Symbols am größten, in der Mitte jedoch weniger ausgeprägt. Ein Muster, das in der Symbolmitte beginnt und endet, weist kleinere Lücken auf als ein Muster, das oben / unten beginnt / endet. Z.B

Zickzack-

... immer noch ein Hack - immer noch nicht narrensicher


1

Ich denke nicht, dass dies eine Funktion in QGIS ist. Allerdings würde ich versuchen, es so zu machen:

  1. Erstellen Sie mit dem Affine-Tool-Plugin zwei Kopien der Ebene. Eine der Schichten mit etwas größerem Maßstab und eine mit etwas kleinerem Maßstab.

  2. Verdichten Sie die Geometrie der Ebenen. Das bedeutet, dass Sie weitere Knoten hinzufügen.

  3. Gehen Sie zur Attributtabelle und benennen Sie jeden Merkmalsknoten folglich 1, 2, 3, ... in einer Schicht und 1b, 2b, 3b, ... in der zweiten Schicht.

  4. füge beide Ebenen zusammen und sortiere die Attributebene -> dies sollte eine Zick-Zack-Linie ergeben.

Vielleicht klappt das ja.


1
Danke für die Antwort! Ich denke jedoch nicht, dass dies funktionieren wird, außer in sehr speziellen Fällen wie einem Kreisbogen mit äquidistanten Scheitelpunkten, da sonst eine ungleichmäßige Zick-Zack-Linie entsteht (aufgrund der Skalierung und der Verdichtung).
Jake
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.