Menyelaraskan beberapa poin ke baris di QGIS?


11

Saya ingin menyelaraskan beberapa titik ke satu garis, atau garis dalam satu lapisan, menggunakan toleransi atau penyangga tertentu di sekitar objek garis. Silakan merujuk ke sketsa sampel yang dilampirkan.

Demi contoh ini, titik terdekat dengan garis dalam gambar SEBELUM berada dalam 5 unit peta garis, sedangkan titik terluar berjarak lebih dari 10 unit peta. Saya ingin mengambil titik terdekat ke garis terdekat, menggunakan toleransi 5 unit peta untuk mencapai hasil dalam gambar SETELAH.

masukkan deskripsi gambar di sini


Jadi titik harus 0 unit peta secara lateral dari garis, tetapi apakah Anda peduli di mana titik berakhir secara longitudinal dari garis sehubungan dengan lokasi asli titik?
Joe

Skenario yang ideal adalah memindahkan titik menggunakan jalur tegak lurus ke garis. Namun, tujuannya adalah untuk menggunakan toleransi yang cukup kecil. Jika titik-titik tersebut dipindahkan secara longitudinal atau latitudinal, ke arah garis, itu tidak akan mengimbangi titik-titik yang jauh dari posisi tegak lurus yang lebih disukai.
Ed Camden

Tidak yakin apakah ini cara terbaik, tetapi satu cara yang dapat saya pikirkan adalah menulis beberapa kode python untuk menganalisis dua set data dan menghasilkan beberapa titik koordinat. Jika ini yang Anda inginkan, beri tahu saya dan saya bisa memberikan jawaban untuk Anda. Misalnya untuk setiap titik, jika nilai absolut lat dist dari garis <= 5 unit, maka jarak lateral = 0. Anda harus mengimpor pustaka gdal untuk mengubah nilai x, y menjadi koordinat. Lihat komentar di: gis.stackexchange.com/questions/185445/…
Joe

Dengan PyQGIS, dapat dihasilkan lapisan memori di mana titik-titik diambil sesuai dengan toleransi 5 unit peta yang sebelumnya dianggap dan jalur tegak lurus ke garis. Lihat jawaban saya.
xunilk

Jawaban:


15

Ada alat bawaan untuk melakukan ini dalam versi QGIS 3.0 yang belum dirilis. Anda bisa mendapatkan potret malam dari situs web QGIS untuk mengujinya terlebih dahulu.

Untuk melakukan ini:

  1. Jalankan algoritma pemrosesan "Jepret geometri ke lapisan"
  2. Pilih layer poin Anda sebagai "lapisan input"
  3. Pilih layer garis sebagai "layer referensi"
  4. Masukkan toleransi yang sesuai (jarak maksimum untuk memindahkan titik saat memotret)
  5. Ubah perilaku menjadi "Pilih titik terdekat"

masukkan deskripsi gambar di sini

Inilah hasilnya, menunjukkan titik asli sebagai "x", dan titik yang diambil sebagai titik hijau. Saya menggunakan toleransi di sini sehingga hanya beberapa titik input yang terputus.

masukkan deskripsi gambar di sini


Inilah yang saya butuhkan. Sayangnya majikan saya hanya menginstal versi LTR dari QGIS dan kami semua dilarang mengunduh dan menginstal versi uji. (menghela nafas) Saya kira ini masalah menunggu. Apakah ini fungsi standar / bawaan atau plug-in?
Ed Camden

Fungsionalitas standar bergantung pada perubahan di kelas c ++ - tidak ada cara untuk menyalin ini secara manual ke versi yang lebih lama. Anda dapat mencoba menginstal menggunakan OSGEO4W pada mesin yang berbeda, dan kemudian menyalin folder osgeo4w ke stik USB untuk dijalankan di workstation Anda. Saya beruntung dengan pendekatan itu di masa lalu.
ndawson

1
Untuk versi lama lihat di plugin ini. docs.qgis.org/2.14/en/docs/user_manual/plugins/…
iRfAn

sepertinya plugin tidak mendukung lapisan poin.
Mykola Kozyr

7

Ini bisa dilakukan dengan PyQGIS . Untuk situasi selanjutnya:

masukkan deskripsi gambar di sini

kode berikut, dengan mempertimbangkan toleransi 5 unit peta, dijalankan di Python Console QGIS:

from math import sqrt

registry = QgsMapLayerRegistry.instance()

points = registry.mapLayersByName('points')
line = registry.mapLayersByName('line')

feat_points = [ feat for feat in points[0].getFeatures() ]
feat_line = line[0].getFeatures().next()

new_points = []

for feat in feat_points:
    pt = feat.geometry().asPoint()
    sqrdist, point, vertex = feat_line.geometry().closestSegmentWithContext(pt)
    if sqrt(sqrdist) <= 5:
        new_points.append(point)
    else:
        new_points.append(pt)

epsg = points[0].crs().postgisSrid()

uri = "Point?crs=epsg:" + str(epsg) + "&field=id:integer""&index=yes"

mem_layer = QgsVectorLayer(uri,
                           'new_points',
                           'memory')

prov = mem_layer.dataProvider()

feats = [ QgsFeature() for i in range(len(new_points)) ]

for i, feat in enumerate(feats):
    feat.setAttributes([i])
    feat.setGeometry(QgsGeometry.fromPoint(new_points[i]))

prov.addFeatures(feats)

QgsMapLayerRegistry.instance().addMapLayer(mem_layer)

Itu menghasilkan lapisan memori di mana titik-titik diambil sesuai dengan toleransi 5 unit peta yang sebelumnya dianggap dan jalur tegak lurus ke garis.

masukkan deskripsi gambar di sini


2

Anda juga dapat melakukan ini di Kalkulator Bidang dengan plugin refFunctions. Anda dapat menggunakan Kalkulator Bidang untuk memperbarui geometri lapisan serta bidang. refFunctions memberi Anda fungsi "geomdistance" untuk menemukan garis terdekat dalam jarak tertentu (atau "geomnearest" jika Anda tidak menginginkan ambang batas) dan akan mengembalikan atribut atau geometri, dan fungsi "terdekat_point" akan menemukan yang terdekat titik pada geometri yang diberikan. Rangkai semuanya seperti itu untuk menghitung geometri baru untuk layer titik Anda:

closest_point(geom_from_wkt(geomdistance('snap_lines','$geometry',10)) , $geometry)

Alih-alih memperbarui geometri secara langsung, Anda dapat menghitung bidang dengan geometri yang terpotong. Saya menyimpan banyak geometri untuk memotret culvert point ke layer stream yang berbeda dan saya dapat dengan mudah memperbarui geometri titik dalam Field Calculator tergantung pada garis stream siapa yang perlu saya gunakan.

Ada beberapa batasan dengan ini, kedua layer harus memiliki CRS yang sama dan fungsi geomdistance akan memberi Anda kesalahan jika Anda memiliki lebih dari 100.000 poin tetapi Anda dapat mengubah batas ini jika Anda mengedit file plugin refFunctions.

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.