18 votos

Símbolo de línea de zigzag en QGIS

Estoy buscando un símbolo de línea de zigzag en QGIS.

He intentado crear una línea de marcador usando un marcador de triángulo simple (^) y ajustando el tamaño del marcador y el intervalo de colocación del marcador hasta que los triángulos se tocaran y parecieran formar una bonita línea de zigzag. Esto funciona para líneas rectas pero alrededor de curvas hay brechas entre los triángulos porque los triángulos no están conectados realmente.

¿Hay quizás una forma de unir los marcadores o otra manera de hacerlo?

Estoy usando QGIS 2.4.0. Mi intento de una línea de zigzag

11voto

Dalroth Puntos 2468

Al parecer, no hay forma de simplemente simbolizar la línea como un zigzag: desafortunadamente, tendrás que modificar los datos subyacentes.

Puedes obtener una línea de zigzag bastante buena dividiendo primero la línea original en muchos segmentos de línea equidistantes, y luego desplazando cada otro punto por una cantidad fija.

Aquí tienes un script en Python que hace esto, tomando la respuesta de NathanW en ¿Cómo puedo crear puntos aleatorios a lo largo de una polilínea en QGIS? como punto de partida. Guarda el fragmento de código en un archivo llamado zigzag.py en tu directorio ~/.qgis/python (o {User Directory}\.qgis\python en Windows), y luego impórtalo en la consola de Python de QGIS escribiendo import zigzag. Luego puedes seleccionar una o más líneas que desees zigzagificar, y escribir zigzag.createZigzag(, ) en la consola de Python de QGIS, donde y son la "longitud" y "anchura" de los segmentos de zigzag, en unidades de mapa.

Aquí tienes un ejemplo:

Como puedes ver, los zigzags no se ven muy bien cerca de las esquinas de la línea original, pero al menos la línea en zigzag no tiene ninguna interrupción.

Si usas la sugerencia de James Conkling de suavizar primero la línea usando el Algoritmo de Chaiken, el resultado será mucho mejor:


Aquí está el script:

from qgis.utils import iface
from qgis.core import *
import numpy as np
from cmath import rect, phase

# Función para calcular la media de dos ángulos.
# Basado en http://rosettacode.org/wiki/Averages/Mean_angle#Python
def meanAngle(a1, a2):
    return phase((rect(1, a1) + rect(1, a2)) / 2.0)

def createZigzag(longitud_onda, amplitud):
    # Crea una nueva capa de memoria para almacenar la línea en zigzag.
    vl = QgsVectorLayer("LineString", "Zigzag", "memory")
    pr = vl.dataProvider()

    # Para cada objeto seleccionado en la capa actual
    layer = iface.mapCanvas().currentLayer()
    for feature in layer.selectedFeatures():
        geom = feature.geometry()

        # Número de segmentos de zigzag
        longitud = geom.length()
        segmentos = np.round(longitud / longitud_onda)

        # Encuentra puntos equiespaciados que aproximan la línea
        puntos = [geom.interpolate(distancia).asPoint() for
            distancia in np.linspace(0, longitud, segmentos)]

        # Calcula los azimuts de los segmentos de línea aproximados
        azimuts = np.radians(
            [puntos[i].azimuth(puntos[i + 1]) for i in range(len(puntos) - 1)])

        # Promedia azimuts consecutivos y rota 90 grados en sentido antihorario
        azimuts_zigzag = [azimuts[0] - np.pi / 2]
        azimuts_zigzag.extend([meanAngle(azimuts[i],
            azimuts[i - 1]) - np.pi / 2 for i in range(len(puntos) - 1)]
        )
        azimuts_zigzag.append(azimuts[-1] - np.pi / 2)

        # Desplaza los puntos a lo largo de los azimuts_zigzag
        puntos_zigzag = []
        for i in range(len(puntos)):
            # Alterna el signo
            dst = amplitud * (1 - 2 * np.mod(i, 2))
            puntos_zigzag.append(
                QgsPoint(puntos[i][0] + np.sin(azimuts_zigzag[i]) * dst,
                    puntos[i][1] + np.cos(azimuts_zigzag[i]) * dst
                )
            )

        # Crea una nueva entidad a partir de la lista de puntos en zigzag
        fet = QgsFeature()
        fet.setGeometry(QgsGeometry.fromPolyline(puntos_zigzag))

        pr.addFeatures([fet])
        vl.updateExtents()

    QgsMapLayerRegistry.instance().addMapLayer(vl)

0 votos

¡Solución excepcional! Mi única pregunta restante es si este algoritmo se puede aplicar en polilíneas.

1 votos

@GaborFarkas: El ejemplo utiliza una polilínea. ¿Quizás te refieres a una capa que contiene varias polilíneas disjuntas (una multinomial)? Eso también funciona.

4voto

Anastasia Puntos 38

He intentado hacer esto antes y no he tenido mucha suerte.

qGIS coloca símbolos repetidos en una línea basados en un punto de referencia (por defecto, el centro, aunque se puede configurar en la parte superior/media/inferior x izquierda/centro/derecha), y rota ese símbolo basado en la pendiente de la línea en ese punto. En una línea recta, donde la pendiente no cambia de un punto de colocación de símbolo a otro, cada símbolo se alineará perfectamente con el anterior. En una curva, sin embargo, ningún punto en un símbolo coincidirá perfectamente con el punto correspondiente en el siguiente símbolo.

símbolo de marcador repetido en qGIS

Entonces, si la línea roja es la línea en sí, repetir un símbolo a lo largo de esa línea resultará en brechas entre los símbolos a lo largo del exterior de una curva, y superposiciones en el interior de una curva.

Para eliminar completamente las brechas y superposiciones, cada cuadrado de símbolo tendría que ser reformado como un rombo de tamaño variable--similar a cómo las piedras de un arco se biselan para coincidir con la curva. Hasta donde sé, no es posible simular algo así. Sin embargo, puedes disminuir la distorsión densificando y suavizando la geometría de tu línea de manera que el cambio de ángulo sea menos extremo. El plugin generalizador puede ayudar con eso (intenta usarlo con el algoritmo de Chaiken).

símbolo de marcador repetido suavizado en qGIS

Además, dividir tu símbolo en segmentos más pequeños y colocar cada uno sucesivamente, de modo que nuevamente disminuyas el ángulo entre cada marcador subsecuente, ayudaría. Por ejemplo, divide tu símbolo de V en un \ y un /, carga ambos en la línea de marcador y para cada uno, establece un desplazamiento-x igual a la mitad de su ancho, positivo para uno y negativo para el otro.

Por último, un trazo de símbolo ligeramente más grueso con extremos redondeados ayudaría a ocultar la ligera distorsión.

Esto sigue siendo un poco de truco--me encantaría escuchar si alguien más tiene un enfoque más confiable.

Edit:

otra idea: el desalineamiento de un símbolo a otro causado por la rotación del símbolo a lo largo de la curva es mayor en la parte superior/inferior del símbolo, pero menos pronunciado en el centro. Así que un patrón que comience y termine en el centro del símbolo tendrá brechas más pequeñas que un patrón que comienza/termina en la parte superior/inferior. Por ejemplo:

zigzag

...todavía es un truco--todavía no es infalible

1voto

palako Puntos 163

No creo que esta sea una característica en QGIS. Sin embargo, intentaría hacerlo de esta manera:

  1. hacer dos copias de la capa usando el complemento Affine Tool. Una de las capas con una escala ligeramente mayor y otra con una escala ligeramente menor.

  2. Densificar la geometría de las capas. Eso significa agregar más nodos.

  3. Ir a la tabla de atributos y nombrar cada nodo de la característica consecuentemente 1,2,3,... en una capa y 1b,2b,3b,... en la segunda capa.

  4. fusionar ambas capas y ordenar la capa de atributos --> esto debería darte una línea en zigzag.

Tal vez esto funcione.

1 votos

¡Gracias por la respuesta! Sin embargo, no creo que esto funcione excepto en casos muy específicos como un arco circular con vértices equidistantes, de lo contrario terminarás con una línea de zigzag desigual (debido a la escala y a la densificación).

0voto

oxullo Puntos 61

Si alguien está interesado, una solución muy dinámica se puede encontrar aquí: dibujando líneas onduladas en qgis

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X