在QGIS中绘制波浪形的线条?


21

是否有QGIS功能或插件来画一条摇摆的线?

我已经使用样条工具手动绘制了一些波形,但是这很耗时。如果可能的话,我想画些类似的东西:

在此处输入图片说明

Inkscape Function Plottersin(x)曲线)。


真有趣的问题!您是否正在考虑一种即时绘制线的工具(例如,当您使用鼠标绘制简单的线特征时),或者是一种从作为输入的坐标开始(最终从点,线或多边形开始)获得此结果的方法?
mgri

1
@mgri感谢您的评论。我希望使用这条线来标记具有某些不确定性的边界(例如波动的海岸线),因此主要思想是将折线(通过预定义的坐标)转换为摆动。但是,立即绘制这种类型的线的想法确实很有吸引力。
Kazuhito

请看看我的解决方案是否有帮助。我并未对其进行广泛的测试,因此请让我知道是否出现问题(我现在无法执行,但我可能会使用更多信息来编辑答案)。
mgri

Answers:


18

我提出了使用PyQGIS的解决方案。它应同时适用于Linestring和MultiLineString图层。

该解决方案基于半圆形环的创建,因此您需要为直径设置一个值(即step下面代码中的变量)。您选择的步骤将不是实际使用的步骤,因为它是根据行长进行调整的(但实际上与初始设置的值相似)。您需要进行一些尝试,然后才能找到step变量的最佳值。

该代码还需要第二个(可选)参数(称为crv_angle),该参数有助于减小或增加圆环的曲率(我对其进行了一些测试,因此建议保留45度作为默认角度,因为它会导致形成实圆戒指)。

您只需要从Python控制台运行以下代码:

from math import sin, cos, radians

step = 3 # choose the proper value (e.g. meters or degrees) with reference to the CRS used
crv_angle = 45 # degrees

def segment(polyline):
    for x in range(0, len(polyline) - 1):
        first_point = polyline[x]
        second_point = polyline[x +1]
        seg = QgsGeometry.fromPolyline([first_point, second_point])
        tmp_azim = first_point.azimuth(second_point)
        len_feat = seg.length()
        parts = int(len_feat/step)
        real_step = len_feat/parts # this is the real step applied

        points = []
        current = 0
        up = True

        while current < len_feat:
            if up:
                round_angle = radians(90 - (tmp_azim - crv_angle))
                up = False
            else:
                round_angle = radians(90 - (tmp_azim + crv_angle))
                up = True
            first = seg.interpolate(current)
            coord_x, coord_y = (first.asPoint().x(), first.asPoint().y())
            p1=QgsPointV2(coord_x, coord_y)
            dist_x, dist_y = ((real_step*sin(rad_crv_angle))* cos(round_angle), (real_step*sin(rad_crv_angle)) * sin(round_angle))
            p2 = QgsPointV2(coord_x + dist_x, coord_y + dist_y)
            points.extend([p1, p2])
            current += real_step

        second = seg.interpolate(current + real_step)
        p3=QgsPointV2(second.asPoint().x(), second.asPoint().y())
        points.append(p3)

        circularRing = QgsCircularStringV2()
        circularRing.setPoints(points) # set points for circular rings
        fet = QgsFeature()
        fet.setGeometry(QgsGeometry(circularRing))
        prov.addFeatures([fet])

layer = iface.activeLayer() # load the input layer as you want
crs = layer.crs().toWkt()
rad_crv_angle = radians(crv_angle)

# Create the output layer
outLayer = QgsVectorLayer('Linestring?crs='+ crs, 'wiggly_line' , 'memory')
prov = outLayer.dataProvider()
fields = layer.pendingFields()
prov.addAttributes(fields)
outLayer.updateFields()

for feat in layer.getFeatures():
    geom = feat.geometry()
    polyline = geom.asPolyline()
    segment(polyline)

# Add the layer to the Layers panel
QgsMapLayerRegistry.instance().addMapLayer(outLayer)

它将创建一个具有预期结果的新行存储层:

在此处输入图片说明


哇!我不能停止玩这个,太华丽了。最重要的是,输出本身可用于进一步的操作,例如缓冲区。谢谢@mgri。最后一件事,有时我会看到在顶点处或顶点附近出现小圆圈。这是可以避免的吗?我可以通过使用Node Tool删除此类圆的中心节点来删除它们(所以没什么大不了的)。
Kazuhito

1
@Kazuhito,请参阅我编辑的代码。离散化似乎出了点问题,我希望现在可以解决。我进行了几次测试,看来效果很好(代码也更具可读性)。
mgri

1
非常感谢@mgri。有些圈子很小,很抱歉,我无法清楚解释它们的出现方式。现在,大多数顶点都是“无圆”的。我注意到的唯一区别是该节点(带圆圈)在“节点工具”的“顶点编辑器”表上显示了较小的“ r值”。这很容易管理,并且比我预期的要好得多。再次感谢你。让我接受您的答案作为解决方案。
Kazuhito

1
谢谢@Kazuhito。对不起,您还没有创建一个完美的解决方案。但是,我希望您会喜欢的(否则,您也可以向我发送一个shapefile示例文件,我将尝试解决此问题)。如果我找到一种更有效的方法,我会发布它!
mgri

1
非常感谢@mgri。如果我在圆圈的外观上发现任何有特色的图案,将以可复制的示例向您更新。这太令人愉快了(它的输出很漂亮)!
Kazuhito

20

简短的答案:您可以使用自定义SVG来获取它。请参阅这篇文章的底部。

长答案:

我认为代表它比修改线的几何形状更好。如果要移动边缘或对几何图形执行其他操作,管理摆动是否是几何图形的一部分而不只是直线的表示将是一场噩梦。

您可以使用样式标记线。有一种方法可以轻松地接近您所需要的内容,而稍加努力,就有可能准确地得到它。 在此处输入图片说明

为此,您可以使用两条标记线设置线条样式。每条标记线均由一个简单标记(半圆)组成。第一个旋转180。两者都设置为透明。

在“标记”行上,指示其中之一要偏移,这样两个符号不会彼此并排绘制,而是并排绘制。如果使用offest = 1/2 *间隔大小,则输出将是正弦曲线。我建议您使用间隔大小,偏移量和符号大小。

这种方法的主要局限性是半圆的直径线,其总和为原始线。如果您的背景是白色(或任何纯色),则可以使用背景色添加第3条简单线。

在此处输入图片说明

在此处输入图片说明

在此处输入图片说明

在此处输入图片说明

** 编辑 **

摆脱中心线的另一种方法是创建一个新的SVG符号。我修改了半曲线,只保留了圆形部分。它可以工作,尽管1/2椭圆可能更有吸引力。屏幕截图使用符号大小10(间隔4,偏移2)完成。

在此处输入图片说明

将下面的代码保存在文件half_circle_line.svg中,并确保将svg的路径设置为 QGIS // Settings / Options / System / SVG Paths

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="11.2889mm" height="11.2889mm"
 viewBox="0 0 32 32"
 xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"  version="1.2" baseProfile="tiny">
<title>Qt Svg Document</title>
<desc>Generated with Qt</desc>
<defs>
</defs>
<g fill="none" stroke="black" stroke-width="1" fill-rule="evenodd" stroke-linecap="square" stroke-linejoin="bevel" >

<g fill="#ffffff" fill-opacity="0" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,0,0)"
font-family="MS Shell Dlg 2" font-size="8.25" font-weight="400" font-style="normal" 
>
<path vector-effect="non-scaling-stroke" fill-rule="evenodd" d="M19.1181,16 C19.1181,16 19.1181,14.2779 17.7221,12.8819 16,12.8819 C14.2779,12.8819 12.8819,14.2779 12.8819,16"/>
</g>
</g>
</svg>

好主意。目前正在努力与持久的“中心线” ...:\
Kazuhito

我也+1。同时,我正在尝试考虑一个PyQGIS解决方案。@Kazuhito,请让我知道这是否对您足够或者您更喜欢物理解决方案。
mgri

@mgri有了这个答案,我现在有了一个“链”而不是“波浪”(试图对其进行修改)。非常希望有一个物理解决方案。
Kazuhito

JGH除了用白线(即您的底图)遮盖外,您是否有删除“中心线”的想法?看起来好像是零散的。
Kazuhito

@Kazuhito-您可以将其更改Pen styleNo Pen :)
约瑟夫(Joseph)
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.