Wygląda na to, że nie ma sposobu, aby po prostu symbolizować linię jako zygzak: niestety będziesz musiał zmienić podstawowe dane.
Można uzyskać dość dobrą linię zygzakowatą, najpierw dzieląc linię oryginalną na wiele odcinków linii w jednakowej odległości, a następnie przesuwając co drugi punkt o ustaloną wartość.
Oto skrypt Pythona, który to robi, biorąc odpowiedź NathanW na: Jak mogę tworzyć losowe punkty wzdłuż polilinii w QGIS? jako punkt wyjścia. Zapisz fragment kodu w pliku o nazwie zigzag.py
w ~/.qgis/python
katalogu (lub {User Directory}\.qgis\python\
w systemie Windows), a następnie zaimportuj go w konsoli QGIS Python, wpisując import zigzag
. Następnie możesz wybrać jedną lub więcej linii, które chcesz zygzakować, i wpisać zigzag.createZigzag(<wavelength>, <amplitude>)
w konsoli QGIS Python, gdzie <wavelength>
i gdzie <amplitude>
są „długość” i „szerokość” zygzakowatych segmentów, w jednostkach mapy.
Oto przykład:
Jak widać, zygzaki nie są zbyt ładne w pobliżu narożników oryginalnej linii, ale przynajmniej linia zygzakowata nie ma żadnych przerw.
Jeśli skorzystasz z sugestii Jamesa Conklinga, aby najpierw wygładzić linię za pomocą Algorytmu Chaikena, wynik staje się znacznie przyjemniejszy:
Oto skrypt:
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)
Próbowałem to zrobić wcześniej i nie miałem szczęścia.
qGIS umieszcza powtarzające się symbole na linii w oparciu o jeden punkt odniesienia (domyślnie środek, chociaż można ustawić go na górny / środkowy / dolny x lewy / środkowy / prawy) i obraca ten symbol na podstawie nachylenia linii w ten punkt. Na linii prostej, gdzie nachylenie nie zmienia się od jednego położenia symbolu do następnego, każdy symbol idealnie zrówna się z poprzednim. Jednak na krzywej żaden punkt na jednym symbolu nie będzie idealnie pasował do odpowiedniego punktu na następnym symbolu.
Tak więc, jeśli czerwona linia jest samą linią, powtarzanie symbolu wzdłuż tej linii powoduje przerwy między symbolami na zewnątrz krzywej i nakłada się na wnętrze krzywej.
Aby całkowicie wyeliminować luki i nakładki, każdy kwadrat symbolu musiałby zostać przekształcony w romb o różnej wielkości - podobnie jak fazowane kamienie na łuku, aby pasowały do krzywej. O ile mi wiadomo, nie można symulować czegoś takiego. Możesz jednak zmniejszyć zniekształcenie, zagęszczając i wygładzając geometrię linii, aby zmiana kąta była mniej ekstremalna. Wtyczki generalizer może w tym pomóc (spróbuj go z algorytmem Chaiken za).
Pomogłoby również podzielenie symbolu na mniejsze segmenty i umieszczanie każdego z nich kolejno, aby ponownie zmniejszyć kąt między każdym kolejnym znacznikiem. Np. Podziel swój
V
symbol na a\
i a/
, załaduj zarówno na linię znacznika, jak i dla każdego, ustaw przesunięcie x równe połowie ich szerokości, dodatnie dla jednego i ujemne dla drugiego.Wreszcie nieco grubszy obrys symbolu z zaokrąglonymi końcami pomógłby maskować niewielkie zniekształcenie.
To wciąż trochę hack - chciałbym usłyszeć, jeśli ktoś ma bardziej niezawodne podejście.
Edytować:
inna myśl: niewspółosiowość jednego symbolu do drugiego spowodowana obrotem symbolu wzdłuż krzywej jest największa na górze / na dole symbolu, ale mniej wyraźna na środku. Tak więc wzorzec, który zaczyna się i kończy w środku symbolu, będzie miał mniejsze przerwy niż wzorzec, który zaczyna się / kończy na górze / na dole. Na przykład
... wciąż hack - wciąż niezawodny
źródło
Nie sądzę, że jest to funkcja QGIS. Chciałbym jednak zrobić to w ten sposób:
wykonaj dwie kopie warstwy za pomocą wtyczki narzędzia Affine. Jedna z warstw o nieco większej skali i jedna o nieco mniejszej skali.
Zagęścić geometrię warstw. Oznacza to, że dodaj więcej węzłów.
Przejdź do tabeli atrybutów i nazwij każdy węzeł funkcji odpowiednio 1,2,3, ... w jednej warstwie i 1b, 2b, 3b, ... w drugiej warstwie.
połącz obie warstwy i posortuj warstwę atrybutu -> powinno to dać linię zygzakowatą.
Może to działa.
źródło