Apa cara paling efisien untuk menemukan ketebalan dinding minimum (nilai dan lokasi) dari area poligon yang kompleks dan tidak cembung termasuk lubang? Lihat contoh poligon berwarna biru, dengan ketebalan dinding minimum berwarna merah, meskipun dalam hal ini lokasinya ambigu, jika dua garis yang berdekatan sejajar.
Sejauh ini, kami telah mencoba:
- Membagi garis poligon dan menemukan garis titik-titik minimum di dalam poligon (brute force, tidak efisien untuk poligon kompleks dengan> 10'000 poin)
- Delaunay triangulasi dan temukan tepi minimal di dalam poligon. Tidak cukup tepat, hanya layak jika dikombinasikan dengan subdivisi garis poligon terlebih dahulu. Inilah contoh (No. 3), di mana triangulasi Delaunay tidak akan menemukan tepi simpleks berwarna merah tetapi akan kehilangan ketebalan dinding minimal di kotak hijau:
- Iteratif meningkatkan buffer erosi untuk menemukan inset minimal, di mana poligon erosi pecah menjadi beberapa bagian = setengah dari ketebalan dinding minimal. Masalahnya adalah untuk menemukan lokasi ketebalan dinding minimum dengan pendekatan ini sesudahnya. Selain itu, erosi tidak selalu pecah menjadi beberapa bagian dan meleset dari "jalan buntu". Berikut adalah contoh (No. 2) yang mengikis ke garis dan memberikan ketebalan dinding minimal yang salah:
- Temukan sumbu medial terlebih dahulu, kemudian cari lingkaran minimum pada sumbu medial yang menutupi tetapi tidak tumpang tindih area poligon. Sunting: Yang bermasalah adalah banyak "kandidat yang salah" pada sumbu medial: Misalnya. (No. 1) lingkaran A akan salah, lingkaran B akan menunjukkan ketebalan dinding minimum yang benar:
Jawaban:
Salah satu metode yang paling efisien untuk menemukan ketebalan dinding minimal (nilai dan lokasi) dari area poligon kompleks, non-cembung termasuk lubang, bisa dengan menggunakan lapisan yang diberi spasi secara teratur (atau acak) dari titik-titik untuk menentukan, pertama, segmen terdekat dengan konteks untuk setiap titik dan, selanjutnya, titik untuk persimpangan antara segmen tambahan dan poligon sisi yang berlawanan; berbasis di cosinus direktur.
Jarak inkremental dapat digunakan sampai segmen pertama mencapai dan memotong beberapa poligon samping (ketebalan dinding minimal).
Untuk mencoba pendekatan saya, saya mengkloning poligon Anda dengan lubang dan membuat layer poin acak di dalam poligon dengan 100 poin; karena dapat diamati pada gambar berikut:
Kode yang digunakan PyQGIS terlihat sebagai berikut:
dan itu menghasilkan lapisan memori jarak inkremental (hanya untuk tujuan visualisasi) dan mencetak ketebalan dinding minimal dalam format WKT.
Setelah menjalankan kode di Python Console dari QGIS saya mendapat hasil gambar berikut:
Dapat diamati bahwa hanya satu jarak tambahan mencapai sisi yang berlawanan pertama di daerah yang diharapkan.
Format WKT tercetak (untuk ketebalan dinding minimal) digunakan dengan plugin QuickWKT dari QGIS untuk memvisualisasikan segmen tersebut pada gambar berikut:
Kecenderungan sedikit dihasilkan karena "segmen terdekat dengan konteks" digabungkan ke sebuah titik; alih-alih poligon samping. Namun, itu bisa dihindari dengan pengecualian kode atau lebih banyak poin.
sumber
Dua ide lagi untuk dilemparkan ke dalam pot:
Rasterisasi poligon Anda dan gunakan transformasi jarak (mengembalikan gambar dari jarak terpendek dari setiap piksel bukan nol ke nol-piksel). Skeletonize gambar raster Anda, lalu ambil nilai jarak dari gambar yang diubah sepanjang kerangka. Dari set itu Anda akan memiliki beberapa minimum yang harus sesuai dengan lebar tersempit Anda. Set ini dapat digunakan sebagai titik pencarian awal untuk kemudian menerapkan pendekatan brute force Anda. Saya harus mencatat bahwa kerangka akan membagi dua sudut-sudut objek, dan pada lokasi-lokasi itu transformasi jarak akan mendekati nol (ketika Anda semakin dekat dengan batas objek). Ini mungkin bermasalah, tetapi merupakan masalah dengan masalah Anda - mengapa bisa ' t lebar terkecil berada di sudut (dan pada dasarnya nol)? Anda bisa mengatasi masalah ini dengan menetapkan ambang batas pada jarak terpendek di sekitar perimeter antara dua titik (jika mereka terletak pada objek yang sama). Anda dapat menggunakan transformasi jarak geodesik pada set piksel perimeter untuk menemukan nilai itu dengan cepat.
Metode ini mengharuskan Anda untuk membuat keputusan tentang resolusi poligon raster, yang memperkenalkan beberapa skala-ketergantungan. Dan jika Anda memilih resolusi yang terlalu tinggi, transformasi jarak dapat memakan waktu. Tetapi umumnya mereka cukup cepat. Metode ini mungkin tidak memberikan Anda presisi yang Anda inginkan, tetapi setidaknya bisa memberi Anda set lokasi yang jauh lebih kecil yang perlu diperiksa.
Metode brute force Anda bukan tempat yang buruk untuk memulai. Saya memiliki masalah yang sama di mana saya harus menemukan semua persimpangan dari garis (panjang) dengan dirinya sendiri, dan saya mampu mempercepat waktu pencarian menggunakan algoritma pencarian pohon kd (saya menggunakan rentang pencarian di Matlab pada saat itu) untuk menemukan poin dalam lingkungan pertama. Dengan begitu Anda hanya memaksa sedikit bagian dari total poin.
sumber
Pendekatan sumbu medial benar, Anda hanya perlu kriteria untuk mengabaikan lingkaran buruk: Setiap lingkaran pada sumbu medial menyentuh permukaan dalam dua (atau lebih) titik. Bayangkan vektor dari pusat lingkaran ke titik-titik ini di permukaan dan amati bahwa sudut antara 180 ° untuk lingkaran B yang baik dan hanya 90 ° untuk lingkaran buruk A.
sumber
Algoritma menggambar poligon generik bekerja dengan menyortir segmen garis dari atas ke bawah, dan bekerja melaluinya untuk menggambar garis piksel orthogonal. Karena cara memecah poligon ini (tanpa lengkungan) sangat cepat, ini dapat digunakan sebagai dasar. Alih-alih hanya pergi dari atas ke bawah, Anda dapat pergi 0, 30, 60, dan 90 derajat, dan menemukan bagian ortogonal terpendek Anda (= ketebalan dinding minimal!), Anda hanya perlu menghitung satu kali per titik dan bukan untuk segala jenis 'resolusi piksel'.
Lihat algoritma komputer-grafik-pindai-garis-poligon-isi
sumber