Simbolo linea a zigzag in QGIS


18

Sto cercando un simbolo di linea a zigzag in QGIS. C'è forse un modo semplice per farlo che mi manca? Ho provato a creare una linea di marker usando un semplice marker a triangolo (^) e regolando la dimensione del marker e l'intervallo di posizionamento del marker fino a quando i traingles non si sono toccati e sembravano creare una bella linea a zig-zag. Questo funziona per le linee rette ma attorno alle curve ci sono degli spazi tra i triangoli perché i triangoli non sono effettivamente collegati. C'è forse un modo per unire i marker? O un altro modo di procedere? Sarei molto grato per eventuali suggerimenti! (usando QGIS 2.4.0) Il mio tentativo di una linea a zigzag

Risposte:


11

Sembra che non ci sia modo di simbolizzare la linea come un zigzag: sfortunatamente, dovrai modificare i dati sottostanti.

Puoi ottenere una linea a zigzag ragionevolmente buona prima dividendo la linea originale in molti segmenti di linea equidistanti, quindi compensando ogni altro punto di un importo fisso.

Ecco uno script Python che lo fa, prendendo la risposta di NathanW a Come posso creare punti casuali lungo una polilinea in QGIS? come punto di partenza. Salvare il blocco di codice in un file chiamato zigzag.pynella ~/.qgis/pythondirectory (o {User Directory}\.qgis\python\su Windows), quindi importarlo nella console QGIS Python digitando import zigzag. Quindi è possibile selezionare una o più righe che si desidera zigzagificare e digitare zigzag.createZigzag(<wavelength>, <amplitude>)la console QGIS Python, dove <wavelength>e <amplitude>sono la "lunghezza" e la "larghezza" dei segmenti a zigzag, in unità della mappa.

Ecco un esempio:

Come puoi vedere, gli zigzag non sono molto belli vicino agli angoli della linea originale, ma almeno la linea a zigzag non ha interruzioni.

Se usi il suggerimento di James Conkling di smussare la linea prima usando l'algoritmo di Chaiken, il risultato diventa molto più bello:


Ecco la sceneggiatura:

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)

Soluzione eccezionale! La mia unica domanda rimasta è se questo algoritmo può essere applicato alle polilinee.
Gabor Farkas,

1
@GaborFarkas: l'esempio usa una polilinea. Intendi forse uno strato contenente diverse polilinee disgiunte (una multi-polilinea)? Funziona pure.
Jake,

3

Ho provato a farlo prima e non ho avuto molta fortuna.

qGIS posiziona i simboli ripetuti su una linea in base a un punto di riferimento (per impostazione predefinita, il centro, sebbene sia possibile impostarlo su alto / medio / basso x sinistra / centro / destra) e ruota quel simbolo in base alla pendenza della linea in quel punto. Su una linea retta, in cui la pendenza non cambia da un posizionamento del simbolo al successivo, ciascun simbolo si allineerà perfettamente con il precedente. Su una curva, tuttavia, nessun punto su un simbolo corrisponderà perfettamente al punto corrispondente sul simbolo successivo.

simbolo marcatore ripetuto in qGIS

Quindi, se la linea rossa è la linea stessa, la ripetizione di un simbolo lungo quella linea si traduce in spazi vuoti tra i simboli lungo l'esterno di una curva e si sovrappone all'interno di una curva.

Per eliminare completamente gli spazi vuoti e le sovrapposizioni, ogni quadrato di simboli dovrebbe essere rimodellato come un rombo di varie dimensioni - simile a come le pietre su un arco vengono smussate per adattarsi alla curva. Per quanto ne so, non è possibile simulare qualcosa del genere. Tuttavia, è possibile ridurre la distorsione densificando e levigando la geometria della linea in modo che il cambio di angolo sia meno estremo. Il plugin generalizer può esserti utile (prova ad usarlo con l'algoritmo di Chaiken).

simbolo marcatore ripetitore levigato in qGIS

Inoltre, rompere il simbolo in segmenti più piccoli e posizionarli in successione, in modo da ridurre di nuovo l'angolo tra ciascun marcatore successivo, sarebbe di aiuto. Ad esempio, spezza il tuo Vsimbolo in a \e a /, carica sia sulla linea del marker sia per ciascuno, imposta un offset x uguale alla metà della loro larghezza, positivo per uno e negativo per l'altro.

Infine, un tratto di simbolo leggermente più spesso con estremità arrotondate contribuirebbe a mascherare la leggera distorsione.

Questo è ancora un po 'un trucco - mi piacerebbe sapere se qualcun altro ha un approccio più affidabile.

Modificare:

un altro pensiero: il disallineamento da un simbolo a un altro causato dalla rotazione del simbolo lungo la curva è maggiore nella parte superiore / inferiore del simbolo, ma meno pronunciato nel mezzo. Quindi un modello che inizia e termina al centro del simbolo avrà spazi più piccoli di un modello che inizia / termina in alto / in basso. Per esempio

zigzag

... ancora un trucco - ancora non infallibile


1

Non penso che questa sia una caratteristica di QGIS. Tuttavia, proverei a farlo in questo modo:

  1. crea due copie del livello usando il plug-in dello strumento Affine. Uno degli strati con una scala leggermente più grande e uno con una scala leggermente più piccola.

  2. Densifica la geometria dei livelli. Ciò significa che aggiungi più nodi.

  3. Vai alla tabella degli attributi e dai un nome a ciascun nodo della funzione di conseguenza 1,2,3, ... in un livello e 1b, 2b, 3b, ... nel secondo livello.

  4. unisci entrambi i livelli e ordina il livello dell'attributo -> questo dovrebbe darti una linea a zigzag.

Forse questo funziona.


1
Grazie per la risposta! Tuttavia, non penso che funzionerà tranne per casi molto specifici come un arco circolare con vertici equidistanti, altrimenti finirai con una linea a zig-zag irregolare (a causa del ridimensionamento e della densificazione).
Jake,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.