QGIS中的曲折线符号


18

我正在寻找QGIS中的锯齿形线符号。可能有一种简单的方法来实现我所缺少的吗?我尝试使用简单的三角形标记(^)创建标记线,并调整标记的大小和标记的放置间隔,直到梯形齿轮相互接触并出现一条不错的锯齿形线。这适用于直线,但是在曲线周围,三角形之间存在间隙,因为三角形实际上没有连接。也许有办法将标记结合在一起吗?还是另一种解决方法?如有任何建议,我将不胜感激!(使用QGIS 2.4.0) 我在曲折线的尝试

Answers:


11

似乎没有办法仅将线符号表示为锯齿形:不幸的是,您必须更改基础数据。

通过先将原始线分成许多等距的线段,然后将每隔一个点偏移固定的量,可以得到一个相当好的之字形线。

这是执行此操作的Python脚本,它采用了NathanW的答案:如何在QGIS中沿折线创建随机点?作为起点。将代码块保存到目录(或Windows)中称为的文件zigzag.py中,然后通过键入将其导入QGIS Python控制台中。然后,您可以选择要进行锯齿形调整的一条或多条线,然后在QGIS Python控制台中键入,其中和分别是以地图单位表示的锯齿形线段的“长度”和“宽度”。~/.qgis/python{User Directory}\.qgis\python\import zigzagzigzag.createZigzag(<wavelength>, <amplitude>)<wavelength><amplitude>

这是一个例子:

如您所见,锯齿形线在原始线条的拐角处不是很好,但是至少锯齿形线没有任何中断。

如果您使用詹姆士·康克林(James Conkling)的建议,首先使用柴肯(Chaiken)算法对直线进行平滑处理,则结果会更好:


这是脚本:

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)

出色的解决方案!我唯一剩下的问题是该算法是否可以应用于折线。
Gabor Farkas 2014年

1
@GaborFarkas:该示例使用折线。您是否意味着包含多个不相交的折线(多折线)的图层?那也一样。
2014年

3

我以前曾尝试过这样做,但运气不太好。

qGIS根据一个参考点(尽管可以将其设置为上/中/下x左/中/右)将重复的符号放置在一条线上,并根据该线的斜率旋转该符号那一点。在一条直线上,斜率不会从一个符号位置变化到下一个符号位置,每个符号将与前一个符号完美对齐。但是,在曲线上,一个符号上的任何点都不会完美匹配下一个符号上的对应点。

qGIS中的重复标记符号

因此,如果红线本身就是线,则沿该线重复符号会导致沿曲线外部的符号之间出现间隙,并在曲线内部重叠。

为了完全消除间隙和重叠,每个符号正方形都需要重塑为大小不同的菱形,这类似于将拱上的石头倒角以匹配曲线的方式。据我所知,不可能模拟这样的东西。但是,您可以通过使线的几何形状致密和平滑化来减少变形,以使角度的变化不太极端。该泛化插件可以与帮助(请尝试使用制作柴肯算法)。

qGIS中平滑的中继器标记符号

另外,将符号分成较小的段并连续放置,这样可以再次减小每个后续标记之间的角度。例如,将V符号分解为a \和a /,将它们同时加载到标记线上,并分别将x偏移设置为其宽度的一半,一个为正,另一个为负。

最后,稍粗的带有圆形末端的符号笔划将有助于掩盖轻微的失真。

这仍然是一个小技巧-很想听听其他人是否有更可靠的方法。

编辑:

另一种想法:由于符号沿曲线的旋转而引起的从一个符号到另一个符号的不对齐在符号的顶部/底部最大,而在中间则不明显。因此,与在顶部/底部开始/终止的模式相比,在符号中心开始和终止的模式将具有较小的间隙。例如

之字形

...仍然是黑客-仍然不是万无一失


1

我认为这不是QGIS的功能。但是我会尝试这样:

  1. 使用Affine工具插件制作该图层的两个副本。其中一层的比例稍大,而另一层的比例略小。

  2. 压实层的几何形状。这意味着添加更多节点。

  3. 转到属性表,然后在每一层中分别命名1,2,3,...,在第二层中命名为1b,2b,3b,...。

  4. 合并两个图层并对属性图层进行排序->这应该给你一条锯齿形的线。

也许这可行。


1
感谢您的回答!但是,除了非常特殊的情况(例如具有等距顶点的圆弧)之外,我认为这不会起作用,否则,最终将出现不均匀的锯齿形线(由于缩放和致密化)。
2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.