Menghubungkan fitur garis dan menentukan panjang garis terpanjang

12

Saya memiliki fitur garis (lihat gambar) yang mewakili sungai yang saya buat menggunakan alat Stream_to_Feature. Tabel atribut berisi beberapa catatan yang mewakili garis yang berbeda - masalahnya adalah garis terpanjang (mudah dibedakan secara visual) tidak direpresentasikan sebagai satu baris dalam tabel, sebenarnya terdiri dari banyak garis yang lebih kecil. Garis-garis itu tampak menyentuh, meskipun tidak saling bersilangan.

Bagaimana saya bisa menggabungkan garis-garis ini dan kemudian menentukan panjang garis terpanjang menggunakan ArcObjects atau metode manual yang dapat saya konversi ke ArcObjects? Solusi yang lebih baik lagi adalah menyingkirkan semua anak sungai dan meninggalkan saya hanya dengan saluran sungai sebagai garis.

Fitur garis - sungai

Radar
sumber
1
Apakah mereka terhubung sama sekali? Anda bilang mereka tidak menyeberang, tetapi apakah itu berarti mereka tidak berbagi titik?
Nathanus
1
Maaf - saya seharusnya lebih jelas. Mereka memang berbagi simpul, tetapi tidak saling menyeberangi satu sama lain.
Radar
Apakah Anda tahu di mana mulut sungai itu? Apakah sungai alway pohon (satu jalur unik dari setiap titik hulu ke mulut)?
Kirk Kuykendall
3
Sebenarnya, Anda tidak ingin panjang "garis terpanjang." Itu bisa berupa rute dari satu jangkauan hulu ke jangkauan hulu terpencil lainnya. Ini akan terjadi ketika dua cabang utama sungai bergabung dekat mulutnya. Sebaliknya, Anda menginginkan rute terpanjang antara mulut dan titik akhir lainnya di sungai. (Karakterisasi ini bahkan tidak mengharuskan aliran direpresentasikan sebagai pohon: ia dapat menjalin dan memiliki pulau.)
whuber
@whuber - penilaian Anda benar - tahu bagaimana saya bisa menyelesaikan ini dengan menggunakan rute?
Radar

Jawaban:

18

Pertama, sedikit latar belakang untuk menunjukkan mengapa ini bukan masalah yang sulit. Aliran melalui sungai menjamin bahwa segmennya, jika terdigitasi dengan benar, selalu dapat berorientasi untuk membentuk grafik asiklik terarah (DAG). Pada gilirannya, grafik dapat dipesan secara linier jika dan hanya jika itu adalah DAG, menggunakan teknik yang dikenal sebagai semacam topologi . Penyortiran topologis cepat: persyaratan waktu dan ruang keduanya O (| E | + | V |) (E = jumlah tepi, V = jumlah simpul), yang sama baiknya dengan yang didapat. Membuat urutan linier seperti itu akan membuatnya mudah untuk menemukan aliran utama.

Di sini, kemudian, adalah sketsa dari suatu algoritma . Mulut sungai itu terletak di sepanjang tempat tidur utamanya. Bergerak hulu sepanjang setiap cabang yang melekat pada mulut (mungkin ada lebih dari satu, jika mulut adalah pertemuan) dan secara rekursif menemukan tempat tidur utama mengarah ke cabang itu. Pilih cabang yang panjang totalnya paling besar: itulah "backlink" Anda di sepanjang ranjang utama.

Untuk memperjelas ini, saya menawarkan beberapa pseudocode (belum diuji) . Input adalah seperangkat segmen garis (atau busur) S (terdiri dari aliran digital), masing-masing memiliki dua titik akhir yang berbeda mulai (S) dan ujung (S) dan panjang positif, panjang (S); dan p muara sungai , yang merupakan titik. Outputnya adalah urutan segmen yang menyatukan mulut dengan titik hulu yang paling jauh.

Kita perlu bekerja dengan "segmen bertanda" (S, p). Ini terdiri dari salah satu segmen S bersama dengan salah satu dari dua titik akhir, hal . Kita perlu menemukan semua segmen S yang berbagi titik akhir dengan titik pemeriksaan q , tandai segmen tersebut dengan titik akhir lainnya , dan mengembalikan set:

Procedure Extract(q: point, A: set of segments): Set of marked segments.

Ketika tidak ada segmen tersebut dapat ditemukan, Ekstrak harus mengembalikan set kosong. Sebagai efek samping, Ekstrak harus menghapus semua segmen yang dikembalikan dari set A, sehingga memodifikasi A itu sendiri.

Saya tidak memberikan implementasi Ekstrak: GIS Anda akan memberikan kemampuan untuk memilih segmen S berbagi titik akhir dengan q . Menandai mereka hanyalah masalah membandingkan mulai (S) dan akhir (S) dengan q dan mengembalikan mana dari dua titik akhir yang tidak cocok.

Sekarang kita siap untuk menyelesaikan masalah.

Procedure LongestUpstreamReach(p: point, A: set of segments): (Array of segments, length)
    A0 = A                        // Optional: preserves A
    C = Extract(p, A0)            // Removes found segments from the set A0!
    L = 0; B = empty array
    For each (S,q) in C:          // Loop over the segments meeting point p
        (B0, M) = LongestUpstreamReach(q, A0)
        If (length(S) + M > L) then
            B = append(S, B0)
            L = length(S) + M
        End if
    End for
    Return (B, L)
End LongestUpstreamReach

Prosedur "append (S, B0)" menempel segmen S di akhir array B0 dan mengembalikan array baru.

(Jika alirannya benar-benar pohon: tidak ada pulau, danau, kepang, dll - maka Anda dapat membuang langkah menyalin A ke A0 .)

Pertanyaan asli dijawab dengan membentuk penyatuan segmen yang dikembalikan oleh LongestUpstreamReach.

Untuk mengilustrasikannya , mari pertimbangkan aliran di peta asli. Misalkan itu didigitalkan sebagai koleksi tujuh busur. Busur a bergerak dari mulut di titik 0 (di atas peta, di kanan pada gambar di bawah, yang diputar) ke arah hulu ke pertemuan pertama di titik 1. Ini busur panjang, katakanlah 8 unit panjang. Arc b bercabang ke kiri (di peta) dan pendek, sekitar 2 unit. Arc c bercabang ke kanan dan panjangnya sekitar 4 unit, dll. Membiarkan "b", "d", dan "f" menunjukkan cabang sisi kiri saat kita pergi dari atas ke bawah pada peta, dan "a", "c", "e", dan "g" cabang lainnya, dan penomoran simpul 0 hingga 7, kita dapat secara abstrak menggambarkan grafik sebagai kumpulan busur

A = {a=(0,1), b=(1,2), c=(1,3), d=(3,4), e=(3,5), f=(5,6), g=(5,7)}

Saya akan kira mereka memiliki panjang 8, 2, 4, 1, 2, 2, 2 untuk sebuah melalui g , masing-masing. Mulutnya adalah simpul 0.

Angka

Contoh pertama adalah panggilan untuk Mengekstrak (5, {f, g}). Ini mengembalikan set segmen yang ditandai {(f, 6), (g, 7)}. Perhatikan bahwa simpul 5 berada pada pertemuan busur f dan g (dua busur di bagian bawah peta) dan bahwa (f, 6) dan (g, 7) menandai masing-masing busur ini dengan titik akhir hulu .

Contoh berikutnya adalah panggilan ke LongestUpstreamReach (0, A). Tindakan pertama yang dilakukan adalah panggilan untuk Mengekstrak (0, A). Ini mengembalikan set yang berisi segmen bertanda (a, 1) dan menghapus segmen a dari set A0 , yang sekarang sama dengan {b, c, d, e, f, g}. Ada satu iterasi dari loop, di mana (S, q) = (a, 1). Selama iterasi ini panggilan dilakukan ke LongestUpstreamReach (1, A0). Secara rekursif, ia harus mengembalikan urutan (g, e, c) atau (f, e, c): keduanya sama-sama valid. Panjang (M) yang dikembalikan adalah 4 + 2 + 2 = 8. (Perhatikan bahwa LongestUpstreamReach tidak mengubah A0 .) Di akhir loop, segmen atelah ditambahkan ke dasar aliran dan panjangnya telah ditingkatkan menjadi 8 + 8 = 16. Dengan demikian nilai pengembalian pertama terdiri dari urutan (g, e, c, a) atau (f, e, c, a), dengan panjang 16 dalam kedua kasus untuk nilai pengembalian kedua. Ini menunjukkan bagaimana LongestUpstreamReach hanya bergerak ke hulu dari mulut, memilih pada setiap pertemuan cabang dengan jarak terpanjang yang belum pergi, dan melacak segmen yang dilalui di sepanjang rute.

Implementasi yang lebih efisien dimungkinkan ketika ada banyak kepang dan pulau, tetapi untuk sebagian besar tujuan akan ada sedikit usaha yang sia-sia jika LongestUpstreamReach dilaksanakan persis seperti yang ditunjukkan, karena pada setiap pertemuan tidak ada tumpang tindih di antara pencarian di berbagai cabang: komputasi waktu (dan kedalaman tumpukan) akan berbanding lurus dengan jumlah total segmen.

whuber
sumber
+1 Sekarang seandainya mereka tahu ini sebelum menamai Sungai Missouri.
Kirk Kuykendall
1
@Kirk Eksplorasi rekursif Amerika Barat di awal 1800-an itu tidak mudah :-).
whuber
ini sangat membantu! Saya akan melihat apakah saya bisa mendapatkan pengaturan ini di dalam GIS saya dan membagikan beberapa kode yang berguna setelah saya membuatnya berfungsi. Bersulang!
Radar
Jawaban yang bagus whuber
Ragi Yaser Burhum
2

Alat Unsplit Line dapat membantu untuk apa yang Anda coba lakukan, meskipun Anda perlu untuk ilahi beberapa metode untuk membedakan satu cabang aliran dari yang lain (untuk bidang yang larut). Ini mengasumsikan Anda memiliki lisensi ArcInfo.

Jika Anda tidak memiliki lisensi seperti itu, Anda dapat mempertimbangkan pendekatan ArcObjects mengambil XY dari setiap titik, mengisi IPointCollectiondengan mereka, dan kemudian membuat IGeometrysebagai PolyLineClass.

Nathanus
sumber
1

Anda dapat menggunakan RivEX itu alat 9.1 ArcGIS (yang akan bekerja di 9.3 dan 10). Ini memiliki alat untuk mengidentifikasi masalah topologi dengan jaringan sungai dan banyak alat pemrosesan. Salah satu alat tersebut menemukan batang utama .

Hornbydd
sumber