Saya perlu menemukan arah jarak terpendek dari satu titik di dunia 2D saya ke titik lain di mana ujung-ujungnya dibungkus (seperti asteroid dll). Saya tahu cara menemukan jarak terpendek tetapi saya berjuang untuk menemukan arahnya.
Jarak terpendek diberikan oleh:
int rows = MapY;
int cols = MapX;
int d1 = abs(S.Y - T.Y);
int d2 = abs(S.X - T.X);
int dr = min(d1, rows-d1);
int dc = min(d2, cols-d2);
double dist = sqrt((double)(dr*dr + dc*dc));
Contoh dunia
:
: T
:
:--------------:---------
: :
: S :
: :
: :
: T :
: :
:--------------:
Dalam diagram, tepi ditunjukkan dengan: dan -. Saya telah menunjukkan pengulangan dunia yang dibungkus di kanan atas juga. Saya ingin menemukan arah dalam derajat dari S ke T. Jadi jarak terpendek adalah ke pengulangan kanan atas dari T. tetapi bagaimana saya menghitung arah dalam degreed dari S ke T yang berulang di kanan atas?
Saya tahu posisi S dan T tetapi saya kira saya perlu menemukan posisi T berulang tetapi ada lebih dari 1.
Sistem koordinat dunia dimulai pada 0,0 di kiri atas dan 0 derajat untuk arah bisa dimulai di Barat.
Sepertinya ini seharusnya tidak terlalu sulit tetapi saya belum dapat menemukan solusi. Saya harap ada yang bisa membantu? Setiap situs web akan dihargai.
Jawaban:
Anda harus mengubah sedikit algoritme Anda untuk menghitung sudut - saat ini Anda hanya merekam perbedaan absolut dalam posisi, tetapi Anda memerlukan perbedaan relatif (yaitu dapat positif atau negatif tergantung pada penentuan posisi).
sumber
MapX
100,T.X
90 danS.X
10dx
seharusnya jelas 20, tetapi algoritma ini akan mengembalikan 30!Di dunia seperti itu ada jumlah tak terbatas dari S ke T. Mari kita tunjukkan koordinat T by
(Tx, Ty)
, koordinat S by(Sx, Sy)
, dan ukuran dunia oleh(Wx, Wy)
. Koordinat terbungkus T adalah(Tx + i * Wx, Ty + j * Wy)
, di manai
danj
adalah bilangan bulat, yaitu elemen dari himpunan{..., -2, -1, 0, 1, 2, ...}
. Vektor yang menghubungkan S ke T adalah(Dx, Dy) := (Tx + i * Wx - Sx, Ty + j * Wy - Sy)
. Untuk(i, j)
pasangan tertentu , jarak adalah panjang vektorsqrt(Dx * Dx + Dy * Dy)
, dan arah dalam radian adalahatan(Dy / Dx)
. Jalur terpendek adalah salah satu dari 9 jalur, di manai
danj
berada di{-1, 0, 1}
:Nilai
i
danj
untuk jalur terpendek dapat ditentukan secara langsung:Terima kasih, @IlmariKaronen, @SamHocevar dan @romkyns atas bantuan Anda!
sumber
abs(Tx-Sx) < Wx/2
, makai=0
itu optimal; jika tidak, pilihan optimal adalahi=-1
ataui=1
, tergantung pada tandaTx-Sx
. Sama berlaku untukTy-Sy
danj
.Hitung satu vektor arah yang mungkin, bahkan jika itu bukan yang terpendek, kemudian bungkus koordinat X-nya sehingga berada dalam
[-MapX/2,MapX/2]
kisaran, dan sama untuk Y:Itu dia! Anda juga mendapatkan jarak tanpa perhitungan lebih lanjut:
sumber
vec2 toroidalNearestWay (vec2 from, vec2 to, vec2 mapSize) { return (mod((to - from + 3.0 * mapSize / 2.0), mapSize)) - mapSize / 2.0; }
Saya kira ada beberapa cara untuk melakukan ini. Inilah 2 yang bisa saya pikirkan di atas kepala saya:
# 1: Menangani kasing secara manual
Tepatnya ada 10 kasus yang bisa terjadi:
S
Untuk setiap ubin di sekitarnya, mereka adalah permutasi dari perhitungan yang berbeda untuk komponen jarak X atau Y. Karena ini adalah jumlah kasus yang terbatas, Anda bisa membuat hard-code bagaimana menghitungnya, dan menemukan jarak terpendek di antara semuanya.
Berikut ilustrasi 2 kasus untuk ditemukan
dx
. Kasus 1, di manaT
berada di ubin yang sama denganS
, dx adilS.x - T.x
. Untuk ubin di sebelah kanan,dx
akan dihitung sebagaiTileWidth - S.x + T.x
.Sebagai optimasi kecil, cari jarak minimum sebelum Anda mengambil akar kuadrat. Kemudian Anda menghemat hingga 7
sqrt
panggilan.# 2: Abstrak koordinat
Jika Anda perlu melakukan sesuatu yang lebih "cair" secara spasial, seperti algoritme pencarian jalur, abaikan saja koordinatnya sehingga algoritme pencarian jalur Anda bahkan tidak menyadari bahwa dunia terbuat dari ubin berulang. Algoritma path-finding dapat menuju arah yang tidak terbatas secara teoritis (ok well Anda akan dibatasi oleh batas numerik, tetapi Anda mendapatkan intinya).
Untuk perhitungan jarak yang sederhana, jangan repot-repot melakukan ini.
sumber
Jangan repot-repot dengan "9 arah". Alasannya adalah bahwa ada 5 kasus yang memburuk di antara mereka 9: "lurus ke utara", "lurus ke barat", "lurus ke selatan", "lurus ke timur" dan "identik". Sebagai contoh, lurus ke utara mengalami kemunduran karena itu merupakan kasus di mana barat laut dan timur laut bergabung dan menghasilkan hasil yang sama.
Dengan demikian, Anda memiliki 4 arah untuk menghitung, dan hanya dapat memilih minimum.
sumber
Terima kasih atas semua jawaban pada akhirnya saya menggunakan Toomai yang diedit oleh Scott Chamberlain. Saya juga telah membuat beberapa perubahan karena fakta bahwa sistem koordinat saya mulai dengan y di kiri atas dan meningkat ketika Anda bergerak ke bawah (pada dasarnya terbalik dibandingkan dengan koordinat grafik normal untuk y).
Saya telah memposting kalau-kalau ada orang lain yang menemukan halaman ini dan memiliki sistem y terbalik yang sama.
sumber
y
di bagian atas. Itu karena perilaku yang diinginkan seharusnya membungkus koordinat di ujung dunia, sedangkan kode yang Anda gunakan mencerminkan koordinat di setiap batas.