¿Dibujar líneas onduladas y onduladas en QGIS?

19

¿Hay una función o complemento de QGIS para dibujar una línea ondulada?

He utilizado la herramienta Spline para dibujar manualmente algunas ondas, pero requiere mucho tiempo. Si es posible, me gustaría dibujar algo como:

Inkscape Function Plotter ( sin(x) curve).

    
pregunta Kazuhito 26.05.2017 - 12:57

2 respuestas

17

Propongo una solución usando PyQGIS. Debería funcionar tanto para las capas Linestring como MultiLineString.

Esta solución se basa en la creación de anillos semicirculares, por lo que necesita establecer un valor para el diámetro (es decir, la variable step en el código a continuación). El paso que elija no será el paso real, ya que se ajusta en función de la longitud de la línea (pero sería realmente similar al valor establecido inicialmente). Debe hacer algunos intentos antes de encontrar el mejor valor para la variable step .

El código también requiere un segundo parámetro (opcional) (llamado crv_angle ), que ayuda a disminuir o aumentar la curvatura de los anillos (realicé algunas pruebas, así que sugiero dejar 45 grados como ángulo predeterminado ya que conduciría a anillos circulares reales).

Solo necesita ejecutar este código desde la Consola 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)

y creará una nueva capa de memoria de línea con el resultado esperado:

    
respondido por el mgri 26.05.2017 - 20:33
20

Respuesta corta: puede obtenerla usando un SVG personalizado. Vea la parte inferior de esta publicación para una.

Respuesta larga:

Creo que es mejor representarlo que modificar la geometría de la línea. Si desea mover un borde o realizar otras acciones en la geometría, sería una pesadilla gestionar si las ondulaciones son parte de la geometría en lugar de solo una representación de una línea recta.

Puedes jugar con la línea del marcador de estilo. Hay una manera de acercarse fácilmente a lo que necesita y, con un poco más de esfuerzo, es posible que lo obtenga exactamente.

Paraobteneresto,debediseñarlalíneacondoslíneasdemarcador.Cadalíneademarcadorestáhechadeunmarcadorsimple,elsemicírculo.Elprimerosegira180grados.Ambosestánconfiguradosentransparente.

EnlalíneadeMarcador,leindicaaunodeellosquesedesplaceparaquelosdossímbolosnosedibujenunofrentealotro,sinounoalladodelotro.Siusaeltamañodeintervalooffest=1/2*,lasalidaseráunacurvasinusoidal.Lesugieroquejuegueconeltamañodeintervalo,eldesplazamientoyeltamañodelossímbolos.

Laprincipallimitaciónconesteenfoqueeslalíneadediámetrodelossemicírculos,quesesumaalalíneaoriginal.Sisufondoesblanco(ocualquiercolorliso),puedeagregarunaterceralíneasimpleusandoelcolordefondo.

**EDIT**

OtraopciónparadeshacersedelalíneacentralescrearunnuevosímboloSVG.Modifiquélamediacurva,soloviviendolaparteredondeada.Funciona,aunqueunaelipse1/2podríasermásatractiva.Lacapturadepantallaserealizóconeltamañodesímbolo10,intervalo4,desplazamiento2.

guardeelcódigoacontinuaciónenelarchivohalf_circle_line.svgyasegúresedequelarutaalsvgestéconfiguradaenQGIS//Settings/Options/System/SVGPaths

<?xmlversion="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>
    
respondido por el JGH 26.05.2017 - 16:15

Lea otras preguntas en las etiquetas