Menghitung panjang poligon di sepanjang garis?

8

Saya perlu menghitung panjang poligon sepanjang / diproyeksikan pada sebuah garis. Gambar untuk menunjukkan gagasan:

masukkan deskripsi gambar di sini

Saya memiliki ribuan poligon untuk "diproyeksikan" pada garis untuk memverifikasi berapa meter dari garis mereka. Poligon tidak beraturan, dengan orientasi yang berbeda, sebagian dari mereka memotong garis, sebagian lagi tidak.

Saya sudah mencoba:

  1. Temukan fitur di sepanjang garis alat di ArcGIS Pro, tetapi hanya memberikan panjang garis untuk tumpang tindih bagian dari poligon (deskripsi alat di sini bantuan ESRI )

  2. Minimum Bounding Geometry dengan opsi 'convex hull', tetapi hanya memberikan jarak antara titik-titik antipodal poligon, yang tidak paralel dengan baris saya (deskripsi alat di sini ESRI membantu

Apakah saya kehilangan alat untuk ini di ArcGIS atau QGIS? Apakah Anda punya solusi untuk ini?

Konrad Gje
sumber
Apakah garis Anda garis lurus?
JiyuuSensei
Karena Anda memiliki persyaratan unik, tampaknya tidak masuk akal bahwa alat seperti itu tidak ada. Anda tentu bisa membuat kode alat seperti itu menggunakan fungsi trigonometri dan berbagai fungsi pembantu geometri, tetapi pertama-tama Anda harus memilih platform perangkat lunak.
Vince
@ JiyuuSensei tidak, sebenarnya ini jaringan polyline - seperti jaringan jalan atau jaringan pipa. Jadi ini harus bekerja seperti menghitung "panjang poligon" ini untuk segmen garis terdekat dari jaringan. Jadi pada dasarnya ide bagaimana fitur Cari di sepanjang alat garis bekerja seperti.
Konrad Gje

Jawaban:

7

Menggunakan QGIS:

(1) Buat layer titik simpul poligon menggunakan alat Ekstrak simpul (dalam QGIS Processing Toolbox> Vector geometry).

masukkan deskripsi gambar di sini

(2) Buka tabel atribut dari layer Vertices yang baru dibuat .

(3) Mulai Kalkulator Bidang dan;

(3A) Buat bidang baru, sebut saja min_poly untuk menyimpan jarak minimum dan memberikan ekspresi:

minimum(
 line_locate_point(
  geometry:=geometry(get_feature_by_id('Lines', '1')), point:=$geometry), 
 group_by:="fid")

NB: Anda perlu mengubah 'Lines'ke nama pengguna baris Anda yang sebenarnya, dan '1'ke id baris yang Anda miliki di tabel atribut Anda.

(3B) Buat bidang baru lain, sebut saja max_poly untuk menyimpan jarak maksimum dan memberikan ekspresi:

maximum(
 line_locate_point(
  geometry:=geometry(get_feature_by_id('Lines', '1')), point:=$geometry), 
 group_by:="fid")

masukkan deskripsi gambar di sini

Karena layer Vertices menjaga bidang fid dari id poligon asli, Anda akan menemukan min_poly dan max_poly adalah jarak minimum / maksimum di sepanjang garis untuk setiap poligon.

(Contoh di atas menunjukkan fid poligon pertama = 1 bentang dari 8,688 hingga 24,45, sedangkan fid poligon kedua = 2 adalah dari 35,062 hingga 42,496).

Kazuhito
sumber
5

Saya tidak tahu bagaimana cara melakukannya dengan QGIS atau ArcGIS tetapi apa yang Anda inginkan terasa seperti lebar kotak pembatas yang berorientasi. Sebagai bukti konsep saya memutar gambar sampel Anda sehingga garis proyeksi horisontal.

masukkan deskripsi gambar di sini

Kemudian saya mendigitalkan poligon dari gambar dan membuat amplop untuk mereka. Lebar amplop menjawab pertanyaan Anda.

masukkan deskripsi gambar di sini

Apa yang hilang adalah alat yang menciptakan kotak pembatas pada sudut tertentu. QGIS memang memiliki alat kotak bounding minimum Berorientasi tetapi pengguna tidak dapat memberikan sudut tetap untuk itu. Mungkin Anda dapat mengadopsi solusi PostGIS dari jawaban yang diterima untuk pertanyaan ini. Menciptakan "kotak pembatas miring" dengan rasio lebar / tinggi maksimum? .

pengguna30184
sumber
Jawaban ini akan menjadi pendekatan terbaik karena sangat mudah untuk mendapatkan kotak pembatas yang berorientasi pada QGIS (dengan lebar dan tinggi amplop) tetapi dua sisi kotak pembatas yang berorientasi ini perlu harus paralel dengan garis referensi dan kondisi ini tidak dijamin . Ini adalah masalah dengan poligon tidak teratur.
xunilk
2

Berdasarkan jawaban @ kazuhito, saya mengumpulkan satu ekspresi tunggal dalam Kalkulator Bidang QGIS yang seharusnya melakukan hal yang sama dalam satu langkah.

Namun saya dapat membayangkan ini akan menjadi sangat padat sumber daya pada dataset yang lebih besar. Saya pikir masalahnya paling cocok untuk implementasi Python, yang jelas menangani referensi dan iterasi yang jauh lebih baik daripada Field Calculator.

array_last(array_sort(array_foreach(
generate_series(1,num_points($geometry)-1),
line_locate_point(aggregate('lines','collect',$geometry),
point_n($geometry,@element))),1)) 
- array_first(array_sort(array_foreach(
generate_series(1,num_points($geometry)-1),
line_locate_point(aggregate('lines','collect',$geometry),
point_n($geometry,@element))),1))

Ini pertama kali membuat 'array' dari nomor node menggunakan generate_series(), menentukan maksimum sebagai jumlah node di setiap poligon - ini adalah num_points($geometry), minus 1 untuk melewati simpul pertama / terakhir yang diulang.

Anda kemudian dapat meneruskan nilai-nilai array ini melalui fungsi untuk menghasilkan array lain menggunakan array_foreach(). Di sini kita meneruskan nomor simpul poligon (diwakili sebagai @element) ke point_n(), yang mengembalikan geometri sebenarnya dari simpul itu, lalu kita masukkan itu ke dalam line_locate_point()untuk menentukan panjangnya di sepanjang garis yang ditentukan (lihat Catatan Penting di bawah).

Array yang dihasilkan kemudian diurutkan dalam urutan naik menggunakan array_sort()yang kemudian memungkinkan kita mendapatkan jarak "paling kiri" dan "paling kanan" di sepanjang garis menggunakan array_last()dan array_first(). Kurangi keduanya dan hasilnya adalah "panjang" poligon di sepanjang garis.

Lihat di bawah untuk contoh ekspresi di atas yang ditampilkan sebagai label dalam poligon (ditambah jarak garis "paling kiri" dan "paling kanan" terpisah dari ekspresi di atas). Sebagai perbandingan, saya juga menyertakan simpul yang diekstraksi dan nilai jarak garis yang relevan. Verteks hijau adalah simpul "paling kiri" dan "paling kanan" di sepanjang garis. Perhatikan poligon kiri-atas di mana titik hijau sebenarnya lebih jauh di sepanjang garis daripada titik di kanan di bawahnya, karena sudut garis ...

Catatan penting :

Geometri lapisan garis dirujuk di sini menggunakan aggregate(). Anda akan perlu mengubah nama layer ( 'lines') seperti yang diperlukan, dan jika Anda memiliki beberapa baris, Anda harus menambahkan filter untuk menentukan jalur Anda ingin membandingkannya dengan, misalnya: aggregate('lines','collect',$geometry,"name"='TrainLine1'). Untuk membuat ini bekerja secara otomatis pada baris terdekat saya sangat merekomendasikan SQL atau Python melalui Field Calc.

Juga, ini menghitung "panjang" dari Polygon SEPANJANG baris, termasuk jika garisnya ditekuk per contoh saya. Jika Anda ingin jarak garis lurus ... mungkin menghitung distance()antara node yang relevan?

masukkan deskripsi gambar di sini

she_weeds
sumber
1

Pendekatan terbaik dalam QGIS untuk melakukan itu (mempertimbangkan ribuan poligon untuk "diproyeksikan" pada garis referensi) adalah menentukan kotak pembatas yang diputar oleh sudut antara garis referensi dan sumbu X. Sudut ini mudah ditentukan dengan menggunakan alat Extract vertices (di QGIS Processing Toolbox -> Vector geometry) untuk garis referensi. Dari contoh gambar berikut, sudut yang diperlukan ditentukan dengan nilai pada tabel atribut layer Vertices menggunakan rumus ini:

90 - 63.91873763467915 = 26.081262365320853 derajat.

masukkan deskripsi gambar di sini

Memperkenalkan sudut di atas dalam Rotate tool dari Processing Toolbox dan jalankan:

masukkan deskripsi gambar di sini

dihasilkan lapisan yang diputar yang memiliki kotak pembatas di tabel atributnya panjang poligon yang diproyeksikan pada garis referensi. Akhirnya dapat diamati dengan menjalankan alat ini dari Memproses Toolbox:

masukkan deskripsi gambar di sini

Pada gambar berikut, panjang poligon yang diproyeksikan pada garis adalah nilai yang ditemukan dalam lebar bidang .

masukkan deskripsi gambar di sini

Dapat diamati pada gambar berikut bahwa panjang yang diproyeksikan dianggap poligon, itu akan seperti yang diharapkan karena garis referensi diputar oleh 26.081262365320853 derajat (diperoleh dengan alat Putar dari Toolbox Pemrosesan) sejajar dengan sumbu X.

masukkan deskripsi gambar di sini

xunilk
sumber