Membuat Thiessen (Voronoi) poligon menggunakan garis (bukan titik) sebagai fitur input?

24

Saya memiliki serangkaian fitur garis di dalam batas poligon tertentu. Untuk setiap baris, saya ingin membuat poligon di dalamnya yang memungkinkan setiap titik lebih dekat ke garis yang diberikan daripada garis lain di lapisan. Saya sudah melakukan ini di masa lalu untuk fitur input titik menggunakan triangulasi Delaunay, tetapi jika ada proses serupa untuk melakukannya dengan fitur garis saya belum dapat menemukannya.

ETA: Solusi Geogeek telah terlintas di benak saya, tetapi di bagian yang lebih lurus di mana garis input memiliki lebih sedikit simpul, poligon yang dihasilkan terlalu dekat (bahkan tumpang tindih) garis yang tidak seharusnya. Di sini, garis merah adalah input saya, Anda dapat melihat simpul dan poligon Thiessen yang dihasilkan dari mereka.

masukkan deskripsi gambar di sini

Mungkin solusi yang cepat dan (sangat) kotor adalah mengubah setiap baris menjadi sekumpulan banyak titik yang berjarak sama (bukan hanya simpul garis), buat poligon Thiessen dari itu, kemudian bubarkan berdasarkan pada ID garis asal.

Dan C
sumber
4
Diagram Voronoi yang mencakup segmen garis bersama dengan titik tidak terdiri dari "poligon"; sebaliknya, sel-sel mereka memiliki batas yang dapat mencakup bagian parabola. Untuk alasan ini, salah satu cara paling efisien dan akurat untuk membuat koneksi Voronoi adalah dengan menggunakan representasi raster. ESRI menyebut prosedur ini Alokasi Euclidean .
whuber

Jawaban:

11

Untuk menggambarkan solusi pemrosesan raster / gambar, saya mulai dengan gambar yang diposting. Kualitasnya jauh lebih rendah daripada data asli, karena superposisi titik biru, garis abu-abu, daerah berwarna, dan teks; dan penebalan garis merah asli. Karena itu ia menghadirkan tantangan: namun, kami masih bisa mendapatkan sel Voronoi dengan akurasi tinggi.

Saya mengekstrak bagian yang terlihat dari fitur linear merah dengan mengurangi hijau dari saluran merah dan kemudian melebarkan dan mengikis bagian paling terang dengan tiga piksel. Ini digunakan sebagai dasar untuk perhitungan jarak Euclidean:

i = Import["http://i.stack.imgur.com/y8xlS.png"];
{r, g, b} = ColorSeparate[i];
string = With[{n = 3}, Erosion[Dilation[Binarize[ImageSubtract[r, g]], n], n]];
ReliefPlot[Reverse@ImageData@DistanceTransform[ColorNegate[string]]]

Plot bantuan

(Semua kode yang ditampilkan di sini adalah Mathematica 8.)

Mengidentifikasi "punggungan" yang jelas - yang harus mencakup semua titik yang memisahkan dua sel Voronoi yang berdekatan - dan menggabungkannya kembali dengan lapisan garis memberikan sebagian besar dari apa yang perlu kita lakukan:

ridges = Binarize[ColorNegate[
   LaplacianGaussianFilter[DistanceTransform[ColorNegate[string]], 2] // ImageAdjust], .65];
ColorCombine[{ridges, string}]

Gambar gabungan

Pita merah melambangkan apa yang saya bisa selamatkan dari garis itu dan pita cyan menunjukkan garis punggungan dalam transformasi jarak. (Masih ada banyak sampah karena jeda pada garis asli itu sendiri.) Punggungan ini perlu dibersihkan dan ditutup melalui pelebaran lebih lanjut - dua piksel akan dilakukan - dan kemudian kita dapat mengidentifikasi daerah terhubung yang ditentukan oleh garis asli dan punggung bukit di antara mereka (beberapa di antaranya perlu secara eksplisit untuk digabungkan kembali):

Dilation[MorphologicalComponents[
  ColorNegate[ImageAdd[ridges, Dilation[string, 2]]]] /. {2 -> 5, 8 -> 0, 4 -> 3} // Colorize, 2]

Apa yang telah dicapai ini, pada dasarnya, adalah mengidentifikasi lima fitur linear yang berorientasi . Kita dapat melihat tiga fitur linear terpisah yang berasal dari titik pertemuan. Masing-masing memiliki dua sisi. Saya telah mempertimbangkan sisi kanan dari dua fitur paling kanan sebagai sama, tetapi sebaliknya membedakan semuanya, memberikan lima fitur. Area berwarna menunjukkan diagram Voronoi dari lima fitur ini.

Hasil

Perintah Alokasi Euclidean berdasarkan pada lapisan yang membedakan tiga fitur linier (yang saya tidak punya untuk ilustrasi ini) tidak akan membedakan sisi yang berbeda dari setiap fitur linier, sehingga akan menggabungkan wilayah hijau dan oranye yang mengapit garis paling kiri ; itu akan membagi fitur teal paling kanan menjadi dua; dan itu akan menggabungkan potongan-potongan itu dengan fitur krem ​​dan magenta yang sesuai di sisi mereka yang lain.

Jelaslah, pendekatan raster ini memiliki kekuatan untuk membangun tessellations Voronoi fitur yang sewenang-wenang - titik, potongan linear, dan bahkan poligon, terlepas dari bentuknya - dan dapat membedakan sisi fitur linear.

whuber
sumber
1
Solusi serupa diilustrasikan di Mathematica.stackexchange.com/questions/20696/… .
whuber
5

Saya pikir kamu bisa:

  • Konversi simpul garis ke titik (line_points).
  • Buat voronoi poligon menggunakan titik (line_points).
  • Larutkan poligon yang dihasilkan menggunakan atribut id yang telah disimpan dari lapisan garis, atau oleh gabungan spasial dengan lapisan garis.

Saya harap saya benar-benar memahami pertanyaan Anda, jika tidak dapatkah Anda memberikan gambar untuk menjelaskan lebih banyak kebutuhan Anda.

geogeek
sumber
2
Saya pikir Anda memahaminya, dan solusi itu terjadi pada saya, tetapi Anda mengalami masalah di mana garis memiliki simpul lebih sedikit. Saya akan memperbarui pertanyaan saya dengan tangkapan layar.
Dan C
3
Ini akan bekerja dengan baik jika Anda membuat poin lebih padat di sepanjang garis. Meskipun pendekatan berbasis raster (seperti whuber menyebutkan dalam komentar pada pertanyaan) saya menduga akan jauh lebih efisien daripada ini.
Andy W