Menggambar garis bergelombang dan bergelombang di QGIS?

21

Apakah ada fungsi atau plugin QGIS untuk menggambar garis miring?

Saya telah menggunakan Spline Tool untuk menggambar beberapa gelombang secara manual, tetapi itu memakan waktu. Jika memungkinkan, saya ingin menggambar sesuatu seperti:

masukkan deskripsi gambar di sini

Inkscape Function Plotter ( sin(x)kurva).

Kazuhito
sumber
Pertanyaan yang sangat menarik! Apakah Anda berpikir tentang alat untuk menggambar garis secara instan (yaitu seperti ketika Anda menggambar fitur garis sederhana menggunakan mouse), atau mungkin cara untuk mendapatkan hasil ini mulai dari koordinat sebagai input (akhirnya dari titik, garis atau poligon)?
mgri
1
@mgri Terima kasih atas komentar Anda. Saya berharap untuk menggunakan garis ini untuk menandai batas dengan beberapa ketidakpastian (seperti garis pantai yang berfluktuasi), jadi ide utama adalah untuk mengubah polyline (melalui koordinat yang ditentukan sebelumnya) menjadi goyangan. Tetapi gagasan untuk menggambar garis jenis ini secara instan juga menarik.
Kazuhito
Tolong, lihat apakah solusi saya membantu. Saya tidak mengujinya secara luas, jadi tolong beri tahu saya jika ada masalah (saya tidak bisa melakukannya sekarang, tetapi saya mungkin akan mengedit jawaban saya dengan informasi lebih lanjut).
mgri

Jawaban:

18

Saya mengusulkan solusi menggunakan PyQGIS. Ini harus bekerja baik untuk lapisan Linestring dan MultiLineString.

Solusi ini didasarkan pada pembuatan cincin setengah lingkaran, jadi Anda perlu menetapkan nilai untuk diameter (yaitu stepvariabel dalam kode di bawah). Langkah yang Anda pilih tidak akan menjadi langkah nyata yang digunakan karena disesuaikan berdasarkan panjang garis (tetapi akan sangat mirip dengan nilai yang awalnya ditetapkan). Anda perlu melakukan beberapa upaya sebelum menemukan nilai terbaik untuk stepvariabel.

Kode juga memerlukan parameter kedua (opsional) (disebut crv_angle), yang membantu untuk mengurangi atau meningkatkan kelengkungan untuk cincin (saya melakukan beberapa tes untuk itu, jadi saya sarankan meninggalkan 45 derajat sebagai sudut standar karena akan mengarah ke lingkaran nyata berdering).

Anda hanya perlu menjalankan kode ini dari Konsol 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)

dan itu akan membuat layer memori baris baru dengan hasil yang diharapkan:

masukkan deskripsi gambar di sini

mgri
sumber
Wow! Saya tidak bisa berhenti bermain dengan ini, sangat cantik. Selain itu, output itu sendiri dapat digunakan untuk operasi lebih lanjut seperti buffer. @Mgri terima kasih Satu hal terakhir, saya terkadang melihat lingkaran kecil muncul di atau dekat simpul. Apakah ini bisa dihindari? Saya dapat menghapusnya dengan menghapus simpul tengah dari lingkaran tersebut dengan Node Tool (jadi ini bukan masalah besar).
Kazuhito
1
@ Kazuhito tolong, lihat kode saya yang diedit. Sepertinya ada sesuatu yang salah dengan diskritisasi dan saya harap sudah diperbaiki sekarang. Saya melakukan beberapa tes dan tampaknya berfungsi dengan baik (kode ini juga lebih mudah dibaca).
mgri
1
Terima kasih banyak @mgri. Ada lingkaran yang sangat kecil, yang saya minta maaf saya tidak bisa menjelaskan dengan jelas bagaimana ini muncul. Sebagian besar simpul sekarang "bebas lingkaran". Hanya perbedaan yang saya perhatikan adalah simpul tersebut (dengan lingkaran) telah menunjukkan "nilai-r" yang lebih kecil pada Tabel Editor Vertex pada Node Tool. Ini mudah dikelola dan jauh lebih baik dari yang saya perkirakan. Terima kasih lagi. Biarkan saya menerima jawaban Anda sebagai solusi.
Kazuhito
1
Terima kasih, @ Kazuhito. Saya minta maaf karena tidak membuat solusi yang sempurna. Namun, saya harap Anda akan menikmatinya (jika tidak, Anda juga dapat mengirim saya sampel shapefile dan saya akan mencoba untuk memperbaiki masalah ini). Jika saya menemukan cara yang lebih efisien, saya akan mempostingnya!
mgri
1
Banyak terima kasih @mgri. Jika saya menemukan pola yang berbeda dalam penampilan lingkaran, saya akan memperbarui Anda dengan contoh direproduksi. Ini sangat menyenangkan (dan hasilnya indah)!
Kazuhito
20

Jawaban singkat: Anda bisa mendapatkannya menggunakan SVG khusus. Lihat bagian bawah posting ini untuk satu.

Jawaban panjang:

Saya percaya lebih baik untuk mewakilinya daripada memodifikasi garis geometri. Jika Anda ingin menggerakkan tepi atau melakukan tindakan lain pada geometri, itu akan menjadi mimpi buruk untuk dikelola jika goyangan adalah bagian dari geometri, bukan hanya representasi dari garis lurus.

Anda dapat bermain dengan garis penanda gaya. Ada cara untuk dengan mudah mendekati apa yang Anda butuhkan, dan dengan sedikit usaha lebih mungkin untuk mendapatkannya dengan tepat. masukkan deskripsi gambar di sini

Untuk mendapatkan ini, Anda akan menata garis dengan dua garis Penanda. Setiap garis Penanda terbuat dari Penanda Sederhana, setengah lingkaran. Yang pertama diputar oleh 180. Keduanya diatur ke transparan.

Pada garis Marker, Anda menginstruksikan salah satu dari mereka untuk diimbangi sehingga kedua simbol tidak ditarik di depan satu sama lain, tetapi berdampingan. Jika Anda menggunakan ukuran interval = 1/2 * offest, output akan menjadi kurva sinusoidal. Saya sarankan Anda bermain dengan ukuran interval, offset dan ukuran simbol.

Keterbatasan utama dengan pendekatan ini adalah garis diameter setengah lingkaran, yang merupakan jumlah garis asli. Jika latar belakang Anda putih (atau warna polos), Anda bisa menambahkan garis sederhana ke-3 menggunakan warna latar belakang.

masukkan deskripsi gambar di sini

masukkan deskripsi gambar di sini

masukkan deskripsi gambar di sini

masukkan deskripsi gambar di sini

** EDIT **

Pilihan lain untuk menghilangkan garis tengah adalah membuat simbol SVG baru. Saya memodifikasi setengah kurva, hanya tinggal bagian yang bulat. Ini bekerja, meskipun ellipse 1/2 mungkin lebih menarik. Tangkapan layar dilakukan menggunakan ukuran simbol 10, interval 4, offset 2.

masukkan deskripsi gambar di sini

simpan kode di bawah ini dalam file half_circle_line.svg dan pastikan path ke svg diatur dalam 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>
JGH
sumber
Ide bagus. Saat ini berjuang dengan "garis tengah" yang gigih ...: \
Kazuhito
+1 dari saya juga. Sementara itu, saya mencoba berpikir untuk solusi PyQGIS. @ Kazuhito, tolong beri tahu saya apakah ini akan cukup untuk Anda atau jika Anda lebih suka solusi fisik .
mgri
@ Maggi Dengan jawaban ini saya memiliki "rantai" bukan "gelombang" sekarang (mencoba memodifikasinya). Akan sangat menghargai memiliki solusi fisik.
Kazuhito
JGH Apakah Anda berpotensi memiliki ide untuk menghapus "garis tengah", selain menutupinya dengan garis putih (yaitu gambar bawah Anda)? Sepertinya itu terfragmentasi.
Kazuhito
@Kuhuhito - Anda dapat mengubah Pen styleke Tidak Pena :)
Joseph