1use crate::matrix::*;
2#[cfg(test)]
3use crate::operator::Dot;
4use crate::quat::Quat;
5use crate::scalar::Scalar;
6use delegate::delegate;
7use num_traits::{float::FloatConst, real::Real, NumAssign};
8use std::ops::{Add, Mul, Sub};
9
10#[derive(Clone, Default, Debug)]
12pub struct QuatR<T: Real + NumAssign + Default + Clone + PartialEq>(pub(crate) Quat<T>);
13
14macro_rules! impl_quatr_partialeq_float {
15 ($type:ty) => {
16 impl PartialEq<QuatR<$type>> for QuatR<$type> {
17 fn eq(&self, other: &Self) -> bool {
18 (&self.0).eq(&other.0)
19 }
20 }
21 };
22}
23
24impl_quatr_partialeq_float!(f32);
25impl_quatr_partialeq_float!(f64);
26
27impl<T: Real + NumAssign + Default + Clone + PartialEq> From<Quat<T>> for QuatR<T> {
28 fn from(q: Quat<T>) -> Self {
29 Self(q)
30 }
31}
32
33impl<T: Real + Default + NumAssign> Add for &QuatR<T> {
34 type Output = QuatR<T>;
35 fn add(self, rhs: Self) -> Self::Output {
36 self.add(rhs)
37 }
38}
39
40impl<T: Real + Default + NumAssign> Add for QuatR<T> {
41 type Output = QuatR<T>;
42 fn add(self, rhs: Self) -> Self::Output {
43 (&self).add(&rhs)
44 }
45}
46
47impl<'a, T: Real + Default + NumAssign> Mul<&'a QuatR<T>> for &'a QuatR<T> {
48 type Output = QuatR<T>;
49 fn mul(self, rhs: Self) -> Self::Output {
50 self.mul(rhs)
51 }
52}
53
54impl<T: Real + Default + NumAssign> Mul<QuatR<T>> for QuatR<T> {
55 type Output = QuatR<T>;
56 fn mul(self, rhs: Self) -> Self::Output {
57 (&self).mul(&rhs)
58 }
59}
60
61impl<T: Real + Default + NumAssign> Mul<T> for &QuatR<T> {
62 type Output = QuatR<T>;
63 fn mul(self, rhs: T) -> Self::Output {
64 self.scale(rhs)
65 }
66}
67
68impl<T: Real + Default + NumAssign> Mul<T> for QuatR<T> {
69 type Output = QuatR<T>;
70 fn mul(self, rhs: T) -> Self::Output {
71 self.scale(rhs)
72 }
73}
74
75impl<T: Real + NumAssign + Copy + Default> Mul<&QuatR<T>> for Scalar<T> {
76 type Output = QuatR<T>;
77 fn mul(self, rhs: &QuatR<T>) -> Self::Output {
78 rhs * self.0
79 }
80}
81
82impl<T: Real + NumAssign + Copy + Default> Mul<QuatR<T>> for Scalar<T> {
83 type Output = QuatR<T>;
84 fn mul(self, rhs: QuatR<T>) -> Self::Output {
85 rhs * self.0
86 }
87}
88
89impl<T: Real + Default + NumAssign> Sub for &QuatR<T> {
90 type Output = QuatR<T>;
91 fn sub(self, rhs: Self) -> Self::Output {
92 self.minus(rhs)
93 }
94}
95
96impl<T: Real + Default + NumAssign> Sub for QuatR<T> {
97 type Output = QuatR<T>;
98 fn sub(self, rhs: Self) -> Self::Output {
99 (&self).minus(&rhs)
100 }
101}
102
103impl<T: Real + Default + NumAssign> QuatR<T> {
104 pub fn init(x: T, y: T, z: T, w: T) -> Self {
105 Self(Quat::init(x, y, z, w))
106 }
107 pub fn lerp(start: Quat<T>, end: Quat<T>, t: T) -> QuatR<T> {
108 Self(Quat::lerp(start, end, t))
109 }
110 pub fn slerp(start: Quat<T>, end: Quat<T>, t: T) -> QuatR<T> {
111 Self(Quat::slerp(start, end, t))
112 }
113 pub fn add(&self, other: &Self) -> Self {
114 Self(&self.0 + &other.0)
115 }
116 pub fn minus(&self, other: &Self) -> Self {
117 Self(&self.0 - &other.0)
118 }
119 pub fn mul(&self, other: &Self) -> Self {
120 Self(&self.0 * &other.0)
121 }
122 pub fn dot(&self, other: &Self) -> T {
123 self.0.dot(&other.0)
124 }
125 delegate! {
126 to self.0 {
127 pub fn x(&self)->T;
128 pub fn y(&self)->T;
129 pub fn z(&self)->T;
130 pub fn w(&self)->T;
131 pub fn x_mut(&mut self) -> & mut T;
132 pub fn y_mut(&mut self) -> & mut T;
133 pub fn z_mut(&mut self) -> & mut T;
134 pub fn w_mut(&mut self) -> & mut T;
135 pub fn norm_squared(&self) -> T;
136 pub fn norm(&self) -> T;
137 #[into]
138 pub fn normalize(&self) -> Self;
139 pub fn normalized(&mut self);
140 #[into]
141 pub fn ln(&self) -> Self;
142 #[into]
143 pub fn pow(&self, t:T) -> Self;
144 #[into]
145 pub fn negate(&self) -> Self;
146 #[into]
147 pub fn conjugate(&self) -> Self;
148 #[into]
149 pub fn scale(&self, s:T) -> Self;
150 pub fn scaled(&mut self, s: T);
151 #[into]
152 pub fn inverse(&self) -> Self;
153 }
154 }
155 #[allow(dead_code)]
156 pub fn init_auto_w(x: T, y: T, z: T) -> Self {
157 let w = T::one() - x * x - y * y - z * z;
158 if w < T::zero() {
159 QuatR(Quat(Matrix::from([[x, y, z, w]])))
160 } else {
161 QuatR(Quat(Matrix::from([[
162 x,
163 y,
164 z,
165 T::from(-1.).unwrap() * w.sqrt(),
166 ]])))
167 }
168 }
169 pub fn init_from_rotation(rot: Matrix<T, 3, 3>) -> Self {
171 let t = rot.trace();
172 if t > T::zero() {
173 let s = T::from(0.5).unwrap() / (t + T::one()).sqrt();
174
175 QuatR(Quat::init(
176 (rot[[2, 1]] - rot[[1, 2]]) * s,
177 (rot[[0, 2]] - rot[[2, 0]]) * s,
178 (rot[[1, 0]] - rot[[0, 1]]) * s,
179 T::one() / s * T::from(0.25).unwrap(),
180 ))
181 } else if rot[[0, 0]] > rot[[1, 1]] && rot[[0, 0]] > rot[[2, 2]] {
182 let s =
183 T::from(2.).unwrap() * (T::one() + rot[[0, 0]] - rot[[1, 1]] - rot[[2, 2]]).sqrt();
184
185 QuatR(Quat::init(
186 T::from(0.25).unwrap() * s,
187 (rot[[0, 1]] + rot[[1, 0]]) / s,
188 (rot[[0, 2]] + rot[[2, 0]]) / s,
189 (rot[[2, 1]] - rot[[1, 2]]) / s,
190 ))
191 } else if rot[[1, 1]] > rot[[2, 2]] {
192 let s =
193 T::from(2.).unwrap() * (T::one() + rot[[1, 1]] - rot[[0, 0]] - rot[[2, 2]]).sqrt();
194
195 QuatR(Quat::init(
196 (rot[[0, 1]] - rot[[1, 0]]) / s,
197 T::from(0.25).unwrap() * s,
198 (rot[[1, 2]] - rot[[2, 1]]) / s,
199 (rot[[0, 2]] - rot[[2, 0]]) / s,
200 ))
201 } else {
202 let s =
203 T::from(2.).unwrap() * (T::one() + rot[[2, 2]] - rot[[0, 0]] - rot[[1, 1]]).sqrt();
204
205 QuatR(Quat::init(
206 (rot[[0, 2]] - rot[[2, 0]]) / s,
207 (rot[[1, 2]] - rot[[2, 1]]) / s,
208 T::from(0.25).unwrap() * s,
209 (rot[[1, 0]] - rot[[0, 1]]) / s,
210 ))
211 }
212 }
213 #[allow(dead_code)]
215 pub fn to_matrix(&self) -> Matrix<T, 4, 4> {
216 let a = self.normalize();
218 let two = T::from(2.).unwrap();
219
220 Matrix::from([
221 [
222 T::one() - two * (a.y() * a.y() + a.z() * a.z()), two * (a.x() * a.y() - a.z() * a.w()),
224 two * (a.x() * a.z() + a.y() * a.w()),
225 T::zero(),
226 ],
227 [
228 two * (a.x() * a.y() + a.z() * a.w()), T::one() - two * (a.x() * a.x() + a.z() * a.z()),
230 two * (a.y() * a.z() - a.x() * a.w()),
231 T::zero(),
232 ],
233 [
234 two * (a.x() * a.z() - a.y() * a.w()), two * (a.z() * a.y() + a.x() * a.w()),
236 T::one() - two * (a.x() * a.x() + a.y() * a.y()),
237 T::zero(),
238 ],
239 [
240 T::zero(), T::zero(),
242 T::zero(),
243 T::one(),
244 ],
245 ])
246 }
247 #[allow(dead_code)]
248 pub fn init_from_axis_angle_degree(axis: Matrix<T, 3, 1>, angle: T) -> Self
249 where
250 T: FloatConst,
251 {
252 Self::init_from_axis_angle_radian(axis, angle.to_radians())
253 }
254 #[allow(dead_code)]
255 pub fn init_from_axis_angle_radian(axis: Matrix<T, 3, 1>, angle: T) -> Self
256 where
257 T: FloatConst,
258 {
259 let two = T::from(2.).unwrap();
260 let radian = ((angle % (two * T::PI())) + two * T::PI()) % (two * T::PI());
261 let axis_adjust = axis.normalize_l2();
262 let sine_half = (radian / T::from(2.).unwrap()).sin();
263 QuatR(Quat::init(
264 axis_adjust[[0, 0]] * sine_half,
265 axis_adjust[[1, 0]] * sine_half,
266 axis_adjust[[2, 0]] * sine_half,
267 (radian / two).cos(),
268 ))
269 }
270 #[allow(dead_code)]
272 pub fn to_axis_angle(&self) -> (Matrix<T, 3, 1>, T) {
273 let q = self.normalize();
274 let k = (T::one() - q.w() * q.w()).sqrt();
275 if k < T::epsilon() {
276 (
277 Matrix::from([[T::one()], [T::zero()], [T::zero()]]),
278 T::zero(),
279 )
280 } else {
281 let vec_x = q.x() / k;
282 let vec_y = q.y() / k;
283 let vec_z = q.z() / k;
284 (
285 Matrix::from([[vec_x], [vec_y], [vec_z]]),
286 T::from(2.).unwrap() * self.w().acos(),
287 )
288 }
289 }
290 #[allow(dead_code)]
292 pub fn rotate_vector(&self, p: Matrix<T, 3, 1>) -> Matrix<T, 3, 1> {
293 let quat_p = QuatR(Quat::init(p[[0, 0]], p[[1, 0]], p[[2, 0]], T::zero()));
294 let temp2 = &(self * &quat_p) * &self.conjugate();
295 Matrix::from([[temp2.x()], [temp2.y()], [temp2.z()]])
296 }
297}
298
299#[test]
300fn test_quatr_convert_axis_angle_0() {
301 use more_asserts::assert_le;
302 use std::f64::consts::PI;
303 let axis = Matrix::from([[1., 2., 3.]]).t();
305
306 let axis_normalize = axis.normalize_l2();
307 let q = QuatR::init_from_axis_angle_degree(axis, 90.);
308 let (a, angle) = q.to_axis_angle();
309 assert_eq!(a, axis_normalize);
310 assert_le!((angle / PI * 180. - 90.).abs(), 1e-9);
311}
312#[test]
313fn test_quatr_convert_axis_angle_1() {
314 use more_asserts::assert_le;
315 use std::f32::consts::PI;
316 let axis = Matrix::from([[1., 2., 3.]]).t();
318
319 let axis_normalize = axis.normalize_l2();
320 let q = QuatR::init_from_axis_angle_degree(axis, 370.);
321 let (a, angle) = q.to_axis_angle();
322 assert_matrix_approx_eq_float(&a, &axis_normalize, 1e-5);
324 assert_le!((angle / PI * 180. - 10.).abs(), 1e-4);
325}
326#[test]
327fn test_quatr_convert_axis_angle_2() {
328 use std::f32::consts::PI;
329 let axis = Matrix::from([[1., 2., 3.]]).t();
331
332 let axis_normalize = axis.normalize_l2();
333 let q = QuatR::init_from_axis_angle_degree(axis, -33.);
334 let (a, angle) = q.to_axis_angle();
335 assert!(
336 ((angle / PI * 180. - (360. - 33.)).abs() < 1e-9 && a == axis_normalize)
337 || ((angle / PI * 180. + (360. - 33.)).abs() < 1e-9 && (a * -1.) == (axis_normalize))
338 );
339}
340#[test]
341fn test_quatr_rotate_point() {
342 use more_asserts::assert_le;
343 use std::f32::consts::PI;
344 let p = Matrix::from([[1., 5., -3.]]).t();
347 let axis = Matrix::from([[1., 0., 0.]]).t();
348
349 let axis_normalize = axis.normalize_l2();
350 let q = QuatR::init_from_axis_angle_degree(axis, 90.);
351 let (a, angle) = q.to_axis_angle();
352 assert_eq!(a, axis_normalize);
353 assert_le!((angle / PI * 180. - 90.).abs(), 1e-5);
354
355 let rot = q.to_matrix();
356
357 let rot_expected = Matrix::from([
358 [1., 0., 0., 0.],
359 [0., 0., -1., 0.],
360 [0., 1., 0., 0.],
361 [0., 0., 0., 1.],
362 ]);
363
364 assert_eq!(rot, rot_expected);
365 let vec_rotated_expected =
369 rot_expected.dot(&Matrix::from([[p[[0, 0]], p[[1, 0]], p[[2, 0]], 1.]]).t());
370
371 let vec_rotated = q.rotate_vector(p);
372
373 assert_matrix_approx_eq_float(
374 &vec_rotated,
375 &Matrix::from([[
376 vec_rotated_expected[[0, 0]],
377 vec_rotated_expected[[1, 0]],
378 vec_rotated_expected[[2, 0]],
379 ]])
380 .t(),
381 1e-6,
382 );
383}