Masalah ini sebenarnya berkaitan dengan roll-over, saya hanya akan menggeneralisasikan di bawah ini seperti:
Saya memiliki tampilan 2D, dan saya memiliki sejumlah persegi panjang dalam suatu area di layar. Bagaimana cara menyebarkan kotak-kotak itu sehingga tidak saling tumpang tindih, tetapi hanya menyesuaikannya dengan gerakan minimal?
Posisi persegi panjang bersifat dinamis dan bergantung pada masukan pengguna, sehingga posisinya bisa di mana saja.
Gambar terlampir menunjukkan masalah dan solusi yang diinginkan
Masalah kehidupan nyata berkaitan dengan rollover, sebenarnya.
Jawaban atas pertanyaan di komentar
Ukuran persegi panjang tidak tetap, dan tergantung pada panjang teks di rollover
Soal ukuran layar, saat ini saya pikir lebih baik mengasumsikan bahwa ukuran layar cukup untuk persegi panjang. Jika ada terlalu banyak persegi panjang dan algo tidak menghasilkan solusi, maka saya hanya perlu mengubah isinya.
Persyaratan untuk 'bergerak minimal' lebih untuk asetika daripada persyaratan teknik mutlak. Seseorang dapat memisahkan dua persegi panjang dengan menambahkan jarak yang sangat jauh di antara mereka, tetapi itu tidak akan terlihat bagus sebagai bagian dari GUI. Idenya adalah untuk mendapatkan rollover / persegi panjang sedekat mungkin dengan sumbernya (yang kemudian akan saya hubungkan ke sumber dengan garis hitam). Jadi baik 'memindahkan satu untuk x' atau 'memindahkan keduanya untuk setengah x' tidak masalah.
Jawaban:
Saya bekerja sedikit dalam hal ini, karena saya juga membutuhkan sesuatu yang serupa, tetapi saya telah menunda pengembangan algoritme. Anda membantu saya untuk mendapatkan beberapa dorongan: D
Saya juga membutuhkan kode sumbernya, jadi ini dia. Saya mengerjakannya di Mathematica, tetapi karena saya belum banyak menggunakan fitur fungsional, saya rasa akan mudah untuk menerjemahkan ke bahasa prosedural apa pun.
Perspektif bersejarah
Pertama saya memutuskan untuk mengembangkan algoritma untuk lingkaran, karena persimpangan lebih mudah dihitung. Itu hanya tergantung pada pusat dan jari-jari.
Saya bisa menggunakan pemecah persamaan Mathematica, dan kinerjanya bagus.
Hanya melihat:
Itu mudah. Saya baru saja memuat pemecah dengan masalah berikut:
Sesederhana itu, dan Mathematica melakukan semua pekerjaannya.
Saya berkata "Ha! Itu mudah, sekarang mari kita pergi ke persegi panjang!". Tapi saya salah ...
Biru Persegi Panjang
Masalah utama dengan persegi panjang adalah menanyakan persimpangan adalah fungsi yang buruk. Sesuatu seperti:
Jadi, ketika saya mencoba memberi makan Mathematica dengan banyak kondisi untuk persamaan ini, kinerjanya sangat buruk sehingga saya memutuskan untuk melakukan sesuatu yang prosedural.
Algoritme saya berakhir sebagai berikut:
Anda mungkin memperhatikan bahwa kondisi "pergerakan terkecil" tidak sepenuhnya terpenuhi (hanya dalam satu arah). Tetapi saya menemukan bahwa memindahkan persegi panjang ke segala arah untuk memuaskannya, terkadang berakhir dengan perubahan peta yang membingungkan bagi pengguna.
Saat saya mendesain antarmuka pengguna, saya memilih untuk memindahkan persegi panjang sedikit lebih jauh, tetapi dengan cara yang lebih dapat diprediksi. Anda dapat mengubah algoritme untuk memeriksa semua sudut dan semua jari-jari yang mengelilingi posisinya saat ini hingga tempat kosong ditemukan, meskipun itu akan jauh lebih menuntut.
Bagaimanapun, ini adalah contoh hasil (sebelum / sesudah):
Edit> Contoh lainnya di sini
Seperti yang Anda lihat, "pergerakan minimum" tidak memuaskan, tetapi hasilnya cukup baik.
Saya akan memposting kode di sini karena saya mengalami masalah dengan repositori SVN saya. Saya akan menghapusnya saat masalah teratasi.
Edit:
Anda juga dapat menggunakan R-Trees untuk menemukan persimpangan persegi panjang, tetapi tampaknya terlalu berlebihan untuk menangani sejumlah kecil persegi panjang. Dan saya belum menerapkan algoritme. Mungkin orang lain dapat mengarahkan Anda ke implementasi yang ada di platform pilihan Anda.
Peringatan! Kode adalah pendekatan pertama .. kualitasnya belum bagus, dan pasti memiliki beberapa bug.
Ini Mathematica.
Utama
HTH!
Edit: Pencarian multi-sudut
Saya menerapkan perubahan dalam algoritme yang memungkinkan untuk mencari ke segala arah, tetapi memberikan preferensi pada sumbu yang dikenakan oleh simetri geometris.
Dengan mengorbankan lebih banyak siklus, ini menghasilkan konfigurasi akhir yang lebih ringkas, seperti yang Anda lihat di bawah ini:
Lebih banyak sampel di sini .
Pseudocode untuk main loop berubah menjadi:
Saya tidak menyertakan kode sumber agar singkatnya, tetapi tanyakan saja jika Anda merasa dapat menggunakannya. Saya pikir, jika Anda melakukannya dengan cara ini, lebih baik beralih ke pohon-R (banyak tes interval diperlukan di sini)
sumber
Ini tebakannya.
Temukan pusat C dari kotak pembatas persegi panjang Anda.
Untuk setiap persegi panjang R yang tumpang tindih dengan yang lain.
Ini secara bertahap menjauhkan persegi panjang dari satu sama lain dan dari tengah semua persegi panjang. Ini akan berhenti karena komponen v dari langkah 4 pada akhirnya akan menyebarkannya dengan sendirinya.
sumber
Saya pikir solusi ini sangat mirip dengan yang diberikan oleh cape1232, tetapi sudah diterapkan, jadi patut dicoba :)
Ikuti diskusi reddit ini: http://www.reddit.com/r/gamedev/comments/1dlwc4/procedural_dungeon_generation_algorithm_explained/ dan lihat deskripsi dan implementasinya. Tidak ada kode sumber yang tersedia, jadi inilah pendekatan saya untuk masalah ini di AS3 (berfungsi persis sama, tetapi membuat persegi panjang tetap sesuai dengan resolusi kisi):
sumber
velocity
adalah jumlah vektor antara pusatnya dan pusat ruangan lain, jika semua ruangan ditumpuk dengan bagian tengah yang sama,velocity.length == 0
untuk semua ruangan dan tidak ada yang akan bergerak. Dengan cara yang sama, jika dua ruangan atau lebih memiliki persegi panjang yang sama dengan pusat yang sama, mereka akan bergerak bersama tetapi akan tetap bertumpuk.Saya sangat suka implementasi b005t3r! Ini berfungsi dalam kasus pengujian saya, namun perwakilan saya terlalu rendah untuk memberikan komentar dengan 2 perbaikan yang disarankan.
Anda tidak boleh menerjemahkan ruangan dengan peningkatan resolusi tunggal, Anda harus menerjemahkan dengan kecepatan yang Anda hitung dengan susah payah! Hal ini membuat pemisahan lebih organik karena ruangan yang berpotongan dalam lebih banyak memisahkan setiap iterasi daripada ruangan yang tidak terlalu berpotongan dalam.
Anda tidak boleh berasumsi velociites kurang dari 0,5 berarti ruangan terpisah karena Anda dapat terjebak dalam kasus di mana Anda tidak pernah terpisah. Bayangkan 2 ruangan berpotongan, tetapi tidak dapat mengoreksi dirinya sendiri karena setiap kali salah satu mencoba untuk mengoreksi penetrasi, mereka menghitung kecepatan yang diperlukan sebagai <0,5 sehingga mereka terus berulang.
Berikut adalah solusi Java (: Cheers!
sumber
Berikut adalah algoritma yang ditulis menggunakan Java untuk menangani sekelompok
Rectangle
s yang tidak diputar . Ini memungkinkan Anda untuk menentukan rasio aspek yang diinginkan dari tata letak dan memposisikan kluster menggunakan parameterisasiRectangle
sebagai titik tautan , yang menjadi orientasi semua terjemahan yang dibuat. Anda juga dapat menentukan jumlah padding yang ingin Anda sebarkanRectangle
.}
Berikut adalah contoh penggunaan
AspectRatio
dari1.2
, aFillPercentage
of0.8
dan aPadding
of10.0
.Ini adalah pendekatan deterministik yang memungkinkan jarak terjadi di sekitar jangkar sambil membiarkan lokasi jangkar itu sendiri tidak berubah. Hal ini memungkinkan tata letak muncul di mana pun Tempat Menarik pengguna berada. Logika untuk memilih posisi cukup sederhana, tetapi menurut saya arsitektur sekitarnya yang mengurutkan elemen berdasarkan posisi awalnya dan kemudian mengulanginya adalah pendekatan yang berguna untuk menerapkan distribusi yang relatif dapat diprediksi. Selain itu, kami tidak mengandalkan tes persimpangan berulang atau semacamnya, hanya membangun beberapa kotak pembatas untuk memberi kami indikasi luas tentang di mana harus menyelaraskan sesuatu; Setelah ini, mengaplikasikan padding muncul secara alami.
sumber
Berikut adalah versi yang mengambil jawaban cape1232 dan merupakan contoh runnable mandiri untuk Java:
sumber