Saltar al contenido

Símbolo de línea en zigzag en QGIS

Solución:

Parece que no hay forma de simbolizar la línea como un zigzag: desafortunadamente, tendrá que alterar los datos subyacentes.

Puede obtener una línea en zigzag razonablemente buena dividiendo primero la línea original en muchos segmentos de línea equidistantes y luego compensando cada dos puntos en una cantidad fija.

Aquí hay un script de Python que hace esto, tomando la respuesta de NathanW a ¿Cómo puedo crear puntos aleatorios a lo largo de una polilínea en QGIS? como punto de partida. Guarde el fragmento de código en un archivo llamado zigzag.py en tus ~/.qgis/python directorio (o {User Directory}.qgispython en Windows) y luego impórtelo en la consola Python de QGIS escribiendo import zigzag. Luego puede seleccionar una o más líneas que desee zigzagificar y escribir zigzag.createZigzag(<wavelength>, <amplitude>) en la consola Python de QGIS, donde <wavelength> y <amplitude> son la “longitud” y el “ancho” de los segmentos en zigzag, en unidades de mapa.

He aquí un ejemplo:

Como puede ver, los zigzags no son muy agradables cerca de las esquinas de la línea original, pero al menos la línea en zigzag no tiene cortes.

Si usa la sugerencia de James Conkling de suavizar la línea primero usando el algoritmo de Chaiken, el resultado se vuelve mucho mejor:


Aquí está el guión:

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)

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

qGIS coloca símbolos repetidos en una línea en función de un punto de referencia (de forma predeterminada, el centro, aunque puede establecerlo en la parte superior / media / inferior x izquierda / centro / derecha) y gira ese símbolo según la pendiente de la línea en ese punto. En línea recta, donde la pendiente no cambia de la ubicación de un símbolo al siguiente, cada símbolo se alineará perfectamente con el anterior. Sin embargo, en una curva, ningún punto de un símbolo coincidirá perfectamente con el punto correspondiente del siguiente símbolo.

símbolo de marcador repetido en qGIS

Entonces, si la línea roja es la línea en sí, la repetición de un símbolo a lo largo de esa línea da como resultado espacios entre los símbolos a lo largo del exterior de una curva y superposiciones en el interior de una curva.

Para eliminar por completo los huecos y superposiciones, cada cuadrado de símbolo debería ser remodelado como un rombo de tamaño variable, similar a cómo se biselan las piedras de un arco para que coincidan con la curva. Hasta donde yo sé, no es posible simular algo así. Sin embargo, puede disminuir la distorsión densificando y suavizando la geometría de su línea para que el cambio de ángulo sea menos extremo. El complemento generalizador puede ayudar con eso (intente usarlo con el algoritmo de Chaiken).

símbolo de marcador repetidor suavizado en qGIS

Además, sería útil dividir su símbolo en segmentos más pequeños y colocar cada uno en sucesión, de modo que nuevamente disminuya el ángulo entre cada marcador posterior. Por ejemplo, rompe tu V símbolo en un y un /, cargue tanto en la línea del marcador como para cada uno, establezca 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 enmascarar la ligera distorsión.

Esto todavía es un truco; me encantaría saber si alguien más tiene un enfoque más confiable.

Editar:

Otro pensamiento: la desalineación de un símbolo a otro causada 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 pronunciada en el medio. Entonces, un patrón que comienza y termina en el centro del símbolo tendrá espacios más pequeños que un patrón que comienza / termina en la parte superior / inferior. P.ej

zigzag

… sigue siendo un truco, todavía no infalible

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *