線をジグザグとして記号化する方法はないようです。残念ながら、基礎となるデータを変更する必要があります。
最初に元の線を多くの等距離線分に分割し、次に一定量だけ他のすべての点をオフセットすることにより、かなり良いジグザグ線を得ることができます。
これを行うPythonスクリプトを次に示します。QGISのポリラインに沿ってランダムポイントを作成するにはどうすればよいかに対するNathanWの回答を参考にしてください。出発点として。ファイルにコードチャンクを保存しzigzag.py
、あなたの中に~/.qgis/python
(またはディレクトリ{User Directory}\.qgis\python\
Windowsの場合)、その後、次のように入力してQGIS Pythonのコンソールでそれをインポートしますimport zigzag
。次に、ジグザグにしたい1つ以上の行を選択zigzag.createZigzag(<wavelength>, <amplitude>)
し、QGIS Pythonコンソールに入力します。ここで<wavelength>
および<amplitude>
は、ジグザグセグメントの「長さ」と「幅」をマップ単位で入力します。
以下に例を示します。
ご覧のとおり、ジグザグは元の線の角の近くではあまり良くありませんが、少なくともジグザグ線には切れ目がありません。
最初にChaikenのアルゴリズムを使用して線を平滑化するというJames Conklingの提案を使用すると、結果はより良くなります。
スクリプトは次のとおりです。
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)