¿Existe una función o complemento QGIS para dibujar una línea ondulada?
He usado Spline Tool para dibujar manualmente algunas ondas, pero lleva mucho tiempo. Si es posible, me gustaría dibujar algo como:
Inkscape Function Plotter ( sin(x)curva).
¿Existe una función o complemento QGIS para dibujar una línea ondulada?
He usado Spline Tool para dibujar manualmente algunas ondas, pero lleva mucho tiempo. Si es posible, me gustaría dibujar algo como:
Inkscape Function Plotter ( sin(x)curva).
Respuestas:
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 debe establecer un valor para el diámetro (es decir, la stepvariable en el código a continuación). El paso que elija no será el paso real utilizado porque se ajusta en función de la longitud de la línea (pero sería muy similar al valor establecido inicialmente). Debe hacer algunos intentos antes de encontrar el mejor valor para la stepvariable.
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 para ello, por lo que sugiero dejar 45 grados como ángulo predeterminado ya que conduciría a una circular real anillos).
Solo necesita ejecutar este código desde la consola de 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:
Respuesta corta: puede obtenerlo usando un SVG personalizado. Ver al final de esta publicación para uno.
Respuesta larga:
Creo que es mejor representarlo que modificar la geometría de la línea. Si desea mover una arista o realizar otras acciones en la geometría, sería una pesadilla administrar si las oscilaciones son parte de la geometría en lugar de solo una representación de una línea recta.
Puedes jugar con la línea de marcador de estilo. Hay una manera de acercarse fácilmente a lo que necesita, y con un poco más de esfuerzo es posible obtenerlo exactamente.

Para obtener esto, debe diseñar la línea con dos líneas de marcador. Cada línea de marcador está hecha de un marcador simple, el semicírculo. El primero se gira 180. Ambos están configurados en transparente.
En la línea de Marcador, le indica a uno de ellos que se desplace para que los dos símbolos no se dibujen uno frente al otro, sino uno al lado del otro. Si usa offest = 1/2 * tamaño de intervalo, la salida será una curva sinusoidal. Te sugiero que juegues con el tamaño del intervalo, el desplazamiento y los tamaños de los símbolos.
La principal limitación con este enfoque es la línea de diámetro de los semicírculos, que se suma a la línea original. Si su fondo es blanco (o cualquier color normal), puede agregar una tercera línea simple usando el color de fondo.
** EDITAR **
Otra opción para deshacerse de la línea central es crear un nuevo símbolo SVG. Modifiqué la media curva, solo viviendo la parte redondeada. Funciona, aunque una 1/2 elipse podría ser más atractiva. La captura de pantalla se realizó con el tamaño de símbolo 10, intervalo 4, desplazamiento 2.
guarde el código a continuación en un archivo half_circle_line.svg y asegúrese de que la ruta al svg esté establecida en 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>
Pen stylea No Pen :)