Saya memiliki dua vektor u dan v. Apakah ada cara untuk menemukan angka empat yang mewakili rotasi dari u ke v?
math
vector
quaternions
sdfqwerqaz1
sumber
sumber
crossproduct
tidak akan valid dalam kasus ini, jadi pertama-tama Anda perlu memeriksadot(v1, v2) > 0.999999
dandot(v1, v2) < -0.999999
, masing-masing, dan mengembalikan quat identitas untuk vektor paralel, atau mengembalikan rotasi 180 derajat (tentang sumbu apa pun) untuk vektor yang berlawanan.sqrt((v1.Length ^ 2) * (v2.Length ^ 2))
sederhanakan menjadiv1.Length * v2.Length
. Saya tidak bisa mendapatkan variasi apa pun dari ini untuk menghasilkan hasil yang masuk akal.Solusi Vektor Setengah Arah
Saya datang dengan solusi yang saya percaya Imbrondir coba hadirkan (meskipun dengan kesalahan kecil, yang mungkin mengapa sinisterchipmunk kesulitan memverifikasinya).
Mengingat bahwa kita dapat membuat angka empat yang mewakili rotasi di sekitar sumbu seperti:
Dan hasil perkalian titik dan silang dari dua vektor yang dinormalisasi adalah:
Mengingat rotasi dari u ke v dapat dicapai dengan memutar theta (sudut antar vektor) di sekitar vektor tegak lurus, terlihat seolah-olah kita dapat secara langsung membuat angka empat yang mewakili rotasi tersebut dari hasil perkalian titik dan silang. ; Namun, sebagaimana berdiri, theta = sudut / 2 , yang berarti bahwa hal itu akan menghasilkan dua kali rotasi yang diinginkan.
Salah satu solusinya adalah dengan menghitung vektor setengah jalan antara u dan v , dan menggunakan perkalian titik dan silang dari u dan vektor setengah jalan untuk membuat angka empat yang mewakili rotasi dua kali sudut antara u dan vektor setengah jalan , yang membawa kita ke v !
Ada kasus khusus, di mana u == -v dan vektor setengah jalan yang unik menjadi tidak mungkin untuk dihitung. Hal ini diharapkan, mengingat banyaknya tak terhingga banyaknya rotasi "busur terpendek" yang dapat membawa kita dari u ke v , dan kita harus memutar 180 derajat di sekitar vektor ortogonal ke u (atau v ) sebagai solusi kasus khusus kita. Ini dilakukan dengan mengambil perkalian silang ternormalisasi dari u dengan vektor lain yang tidak sejajar dengan u .
Kode semu mengikuti (jelas, pada kenyataannya kasus khusus harus memperhitungkan ketidakakuratan floating point - mungkin dengan memeriksa produk titik terhadap beberapa ambang daripada nilai absolut).
Perhatikan juga bahwa tidak ada kasus khusus ketika u == v (angka empat identitas dihasilkan - periksa dan lihat sendiri).
The
orthogonal
mengembalikan fungsi vektor ortogonal terhadap vektor yang diberikan. Implementasi ini menggunakan perkalian silang dengan vektor basis paling ortogonal.Solusi Kuarter Setengah Jalan
Ini sebenarnya adalah solusi yang disajikan dalam jawaban yang diterima, dan tampaknya sedikit lebih cepat daripada solusi vektor setengah jalan (~ 20% lebih cepat menurut pengukuran saya, meskipun jangan percaya begitu saja). Saya menambahkannya di sini jika orang lain seperti saya tertarik dengan penjelasannya.
Pada dasarnya, alih-alih menghitung angka empat menggunakan vektor setengah jalan, Anda dapat menghitung angka empat yang menghasilkan dua kali rotasi yang diperlukan (seperti yang dijelaskan dalam solusi lain), dan mencari angka empat setengah jalan antara itu dan nol derajat.
Seperti yang saya jelaskan sebelumnya, angka empat untuk dua kali lipat rotasi yang diperlukan adalah:
Dan angka empat untuk rotasi nol adalah:
Menghitung angka empat setengah jalan hanyalah masalah menjumlahkan angka empat dan menormalkan hasilnya, seperti halnya vektor. Akan tetapi, seperti halnya dengan vektor, kuaternion harus memiliki besaran yang sama, jika tidak, hasilnya akan miring ke arah kuaternion dengan besaran yang lebih besar.
Sebuah angka empat dibangun dari titik dan produk silang dari dua vektor akan memiliki magnitudo yang sama seperti produk tersebut:
length(u) * length(v)
. Daripada membagi keempat komponen dengan faktor ini, kita dapat meningkatkan skala angka identitas. Dan jika Anda bertanya-tanya mengapa jawaban yang diterima tampaknya memperumit masalah dengan menggunakansqrt(length(u) ^ 2 * length(v) ^ 2)
, itu karena panjang kuadrat sebuah vektor lebih cepat dihitung daripada panjangnya, jadi kita dapat menyimpan satusqrt
perhitungan. Hasilnya adalah:Dan kemudian menormalkan hasilnya. Kode pseudo berikut:
sumber
Masalah seperti yang dinyatakan tidak terdefinisi dengan baik: tidak ada rotasi unik untuk pasangan vektor tertentu. Perhatikan kasusnya, misalnya, di mana u = <1, 0, 0> dan v = <0, 1, 0> . Satu rotasi dari u ke v akan menjadi rotasi pi / 2 di sekitar sumbu z. Rotasi lain dari u ke v akan menjadi rotasi pi di sekitar vektor <1, 1, 0> .
sumber
Mengapa tidak merepresentasikan vektor menggunakan quaternions murni? Lebih baik jika Anda menormalkannya terlebih dahulu.
q 1 = (0 u x u y u z ) '
q 2 = (0 v x v y v z )'
q 1 q rot = q 2
Pra-kalikan dengan q 1 -1
q rot = q 1 -1 q 2
dimana q 1 -1 = q 1 konj / q norma
Ini dapat dianggap sebagai "divisi kiri". Pembagian kanan, yang tidak diinginkan adalah:
q rot, right = q 2 -1 q 1
sumber
Saya tidak terlalu bagus di Quaternion. Namun saya berjuang selama berjam-jam dalam hal ini, dan tidak dapat membuat solusi Polaris878 berfungsi. Saya sudah mencoba melakukan pra-normalisasi v1 dan v2. Normalisasi q. Normalisasi q.xyz. Namun tetap saja saya tidak mengerti. Hasilnya masih belum memberikan hasil yang benar.
Pada akhirnya saya menemukan solusi yang berhasil. Jika itu membantu orang lain, inilah kode kerja saya (python):
Kasus khusus harus dibuat jika v1 dan v2 adalah paralel seperti v1 == v2 atau v1 == -v2 (dengan beberapa toleransi), di mana saya yakin solusinya harus Quaternion (1, 0,0,0) (tanpa rotasi) atau Quaternion (0, * v1) (rotasi 180 derajat)
sumber
quat = diffVectors(v1, v2); assert quat * v1 == v2
.angle
mendapatkan nilainya dari perkalian titik.Beberapa jawaban tampaknya tidak mempertimbangkan kemungkinan bahwa perkalian silang bisa menjadi 0. Cuplikan di bawah ini menggunakan representasi sumbu-sudut:
Hal tersebut
toQuaternion
dapat diimplementasikan sebagai berikut:Jika Anda menggunakan perpustakaan Eigen, Anda juga dapat melakukan:
sumber
toQuaternion(axis, ang)
-> Anda lupa menentukan apa ituang
angle
adalah bagian dari representasi sudut sumbu dari kuaternion, diukur dalam radian.Dari sudut pandang algoritma, solusi tercepat terlihat di pseudocode
Pastikan Anda membutuhkan satuan satuan (biasanya, diperlukan untuk interpolasi).
CATATAN: Quaternions nonunit dapat digunakan dengan beberapa operasi lebih cepat dari unit.
sumber