Simbol Garis Zigzag di QGIS


18

Saya mencari simbol garis zigzag di QGIS. Apakah mungkin ada cara mudah untuk melakukan ini yang saya lewatkan? Saya telah mencoba membuat garis marker menggunakan marker segitiga sederhana (^) dan menyesuaikan ukuran marker dan interval penempatan marker hingga traingles menyentuh satu sama lain dan muncul untuk membuat garis zigzag yang bagus. Ini berfungsi untuk garis lurus tetapi di sekitar kurva ada celah di antara segitiga karena segitiga sebenarnya tidak terhubung. Apakah mungkin ada cara untuk menggabungkan penanda? Atau cara lain untuk melakukannya? Saya akan sangat berterima kasih atas sarannya! (menggunakan QGIS 2.4.0) Usaha saya di garis zig-zag

Jawaban:


11

Sepertinya tidak ada cara untuk hanya melambangkan garis sebagai zigzag: sayangnya, Anda harus mengubah data yang mendasarinya.

Anda bisa mendapatkan garis zigzag yang cukup baik dengan terlebih dahulu membagi garis asli menjadi banyak segmen garis yang sama, dan kemudian mengimbangi setiap titik lainnya dengan jumlah yang tetap.

Berikut ini adalah skrip Python yang melakukan ini, dengan mengambil jawaban NathanW untuk Bagaimana saya bisa membuat titik acak di sepanjang polyline di QGIS? sebagai titik awal. Simpan potongan kode ke file yang disebut zigzag.pydi ~/.qgis/pythondirektori Anda (atau {User Directory}\.qgis\python\di Windows), lalu impor di konsol Python QGIS dengan mengetik import zigzag. Kemudian Anda dapat memilih satu atau lebih baris yang ingin Anda zigzagify, dan ketik zigzag.createZigzag(<wavelength>, <amplitude>)konsol QGIS Python, di mana <wavelength>dan <amplitude>merupakan "panjang" dan "lebar" dari segmen zigzag, dalam unit peta.

Ini sebuah contoh:

Seperti yang Anda lihat, zigzag tidak terlalu bagus di dekat sudut garis asli, tetapi setidaknya garis zigzag tidak memiliki jeda.

Jika Anda menggunakan saran James Conkling untuk memperhalus garis terlebih dahulu menggunakan Algoritma Chaiken, hasilnya menjadi jauh lebih baik:


Ini skripnya:

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)

Solusi luar biasa! Satu-satunya pertanyaan saya yang tersisa adalah apakah algoritma ini dapat diterapkan pada polyline.
Gabor Farkas

1
@GaborFarkas: Contoh ini menggunakan polyline. Apakah Anda mungkin maksudnya lapisan yang mengandung beberapa polylines terpisah (multi-polyline)? Itu juga berfungsi.
Jake

3

Saya sudah mencoba melakukan ini sebelumnya dan belum beruntung.

qGIS menempatkan simbol berulang pada garis berdasarkan pada satu titik referensi (secara default, tengah, meskipun Anda dapat mengaturnya ke atas / tengah / bawah x kiri / tengah / kanan), dan memutar simbol itu berdasarkan kemiringan garis pada titik itu. Pada garis lurus, di mana kemiringan tidak berubah dari satu penempatan simbol ke yang berikutnya, setiap simbol akan berbaris sempurna dengan yang sebelumnya. Namun pada kurva, tidak ada titik pada satu simbol yang akan cocok dengan titik yang sesuai pada simbol berikutnya.

simbol penanda yang diulang dalam qGIS

Jadi, jika garis merah adalah garis itu sendiri, mengulangi simbol di sepanjang garis itu menghasilkan kesenjangan antara simbol di sepanjang bagian luar kurva, dan tumpang tindih di bagian dalam kurva.

Untuk sepenuhnya menghilangkan celah dan tumpang tindih, setiap simbol persegi perlu dibentuk kembali sebagai belah ketupat dengan berbagai ukuran - mirip dengan bagaimana batu pada lengkungan miring agar sesuai dengan kurva. Sejauh yang saya tahu, tidak mungkin untuk mensimulasikan sesuatu seperti itu. Tetapi, Anda dapat mengurangi distorsi dengan memadatkan dan menghaluskan garis geometri Anda sehingga perubahan sudutnya tidak terlalu ekstrem. The generalizer Plugin dapat membantu dengan itu (coba menggunakannya dengan algoritma Chaiken ini).

simbol marker repeater dihaluskan dalam qGIS

Selain itu, memecah simbol Anda menjadi segmen yang lebih kecil dan menempatkan masing-masing berturut-turut, sehingga sekali lagi Anda mengurangi sudut antara setiap penanda berikutnya, akan membantu. Misalnya, pisahkan Vsimbol Anda menjadi a \dan a /, muat keduanya pada garis penanda dan untuk masing-masing, atur x-offset sama dengan setengah lebar mereka, positif untuk satu dan negatif untuk yang lain.

Terakhir, simbol stroke yang sedikit lebih tebal dengan ujung membulat akan membantu menutupi sedikit distorsi.

Ini masih sedikit peretasan - akan senang mendengar jika ada orang lain yang memiliki pendekatan yang lebih andal.

Edit:

pemikiran lain: ketidaksejajaran dari satu simbol ke simbol lainnya yang disebabkan oleh rotasi simbol di sepanjang kurva adalah yang terbesar di bagian atas / bawah simbol, tetapi kurang menonjol di tengah. Jadi pola yang dimulai dan berakhir di pusat simbol akan memiliki celah yang lebih kecil daripada pola yang dimulai / berakhir di bagian atas / bawah. Misalnya

zigzag

... masih berupa peretasan - masih tidak mudah


1

Saya tidak berpikir bahwa ini adalah fitur di QGIS. Namun saya akan mencoba melakukannya dengan cara ini:

  1. buat dua salinan layer menggunakan plugin Affine tool. Salah satu lapisan dengan skala yang sedikit lebih besar dan satu dengan skala yang sedikit lebih kecil.

  2. Densifikasi geometri lapisan. Itu berarti menambahkan lebih banyak node.

  3. Pergi ke tabel atribut dan beri nama setiap node fitur 1,2,3, ... dalam satu layer dan 1b, 2b, 3b, ... di layer kedua.

  4. menggabungkan kedua layer dan mengurutkan layer atribut -> ini akan memberi Anda garis zigzag.

Mungkin ini berhasil.


1
Terima kasih atas jawabannya! Namun, saya tidak berpikir ini akan bekerja kecuali untuk kasus yang sangat spesifik seperti busur lingkaran dengan simpul yang sama, jika tidak Anda akan berakhir dengan garis zigzag yang tidak rata (karena penskalaan dan karena densifikasi).
Jake
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.