Saya telah mengalami beberapa masalah dengan menentukan secara efisien apakah kamar besar disegel dalam ruang 3D berbasis voxel. Saya pada titik di mana saya telah berusaha sekuat tenaga untuk menyelesaikan masalah tanpa meminta bantuan, tetapi tidak mencoba cukup untuk menyerah, jadi saya meminta bantuan.
Untuk memperjelas, disegel adalah bahwa tidak ada lubang di ruangan. Ada sealer oksigen, yang memeriksa apakah ruangan disegel, dan segel tergantung pada tingkat input oksigen.
Saat ini, inilah yang saya lakukan:
- Mulai dari blok di atas ubin sealer (lubang ada di wajah atas sealer), secara loop berulang melalui semua 6 arah yang berdekatan
- Jika ubin yang berdekatan penuh, non-vakum, lanjutkan melalui loop
- Jika ubin yang berdekatan tidak penuh, atau merupakan ubin vakum, periksa apakah blok yang berdekatan adalah, secara rekursif.
- Setiap kali ubin dicentang, kurangi penghitung
- Jika penghitungan mencapai nol, jika blok terakhir berbatasan dengan ubin vakum, kembalikan bahwa area tersebut tidak disegel
- Jika penghitungan mencapai nol dan blok terakhir bukan ubin vakum, atau loop rekursif berakhir (tidak ada ubin vakum tersisa) sebelum penghitung adalah nol, area disegel
Jika area tidak disegel, jalankan loop lagi dengan beberapa perubahan:
- Memeriksa blok yang berdekatan untuk ubin "udara bernapas" bukan ubin vakum
- Alih-alih menggunakan penghitung pengurangan, lanjutkan sampai tidak ada ubin "udara bernafas" yang berdekatan ditemukan.
- Setelah loop selesai, atur setiap blok yang dicentang ke ubin vakum.
Berikut kode yang saya gunakan: http://pastebin.com/NimyKncC
Masalah:
Saya menjalankan pemeriksaan ini setiap 3 detik, kadang-kadang sealer harus melewati ratusan blok, dan sebuah dunia besar dengan banyak sealer oksigen, beberapa loop rekursif ini setiap beberapa detik bisa sangat sulit pada CPU.
Saya bertanya-tanya apakah ada orang yang lebih berpengalaman dengan optimasi dapat membantu saya, atau setidaknya mengarahkan saya ke arah yang benar. Terima kasih banyak.
Jawaban:
Solusi terbaik akan bergantung pada banyak faktor, seperti ukuran ruangan yang diharapkan.
Pendekatan 1:
Anda dapat menggunakan A * untuk menemukan jalur dari lubang angin ke ubin di atas lubang angin / lubang angin itu sendiri atau ke ubin yang dikenal sebagai vaccum. Jika jalur ditemukan, kamar tidak tertutup. Ini tidak jauh berbeda dari pendekatan Anda saat ini tetapi harus lebih cepat. Setelah ditemukan, buat "fill banjir" untuk mengatur ubin sebagai ruang hampa.
Pendekatan 2:
Mungkin struktur luar Anda kurang pas - mengingat, bahwa ada permukaan di mana kamar-kamarnya, Anda tidak perlu bergerak ke semua 6 arah, jadi Anda harus melakukan perjalanan sepanjang permukaan, tandai setiap ubin sebagai ruang hampa udara yang Anda bawa.
sumber
Saat Anda melakukan pencarian berulang, apakah Anda memastikan Anda tidak memeriksa voxel yang sama beberapa kali? Saya tidak tahu dari cara Anda mendeskripsikan algoritma Anda, tetapi Anda harus memiliki semacam flag untuk menunjukkan apakah Anda telah memperluas voxel secara rekursif, jadi Anda tidak melakukannya lebih dari sekali.
Dan seperti dikatakan Byte56, Anda juga harus memeriksa kebocoran ketika ada perubahan. Itu bisa sangat meminimalkan jumlah pekerjaan yang Anda lakukan, tergantung pada seberapa sering perubahan terjadi. Anda bahkan dapat menyimpan informasi antara panggilan berurutan ke algoritme, yang dapat meremehkan jumlah perhitungan yang Anda lakukan setelah panggilan pertama.
Edit:
Saya melihat beberapa kode Anda. Sepertinya Anda menggunakan LinkedList untuk menunjukkan apakah voxel sudah diperiksa, seperti pada paragraf pertama saya. Anda mungkin memiliki hasil yang lebih baik jika Anda menggunakan sesuatu selain LinkedList untuk ini. Mungkin mencoba HashSet atau sesuatu? Ini harus mengurangi kompleksitas metode pemeriksaan Anda dari O (n) ke O (1).
sumber