use crate::{RealField, Vector3};
mod algebra;
mod arithmetic;
mod cast;
mod display;
mod identity;
mod neg;
mod ops;
mod ops_shared;
mod rotation;
#[derive(Copy, Clone, PartialEq, PartialOrd, Default, Debug)]
pub struct Quaternion<F> {
pub w: F, pub x: F, pub y: F, pub z: F, }
pub type Quaternion32 = Quaternion<f32>;
pub type Quaternion64 = Quaternion<f64>;
impl<F> Quaternion<F>
where
F: RealField,
{
pub fn new(w: F, x: F, y: F, z: F) -> Self {
Quaternion { w, x, y, z }
}
pub fn from_real(re: F) -> Self {
Quaternion {
w: re,
x: F::zero(),
y: F::zero(),
z: F::zero(),
}
}
pub fn identity() -> Self {
Quaternion {
w: F::one(),
x: F::zero(),
y: F::zero(),
z: F::zero(),
}
}
pub fn from_axis_angle(axis: Vector3<F>, angle: F) -> Self {
let half_angle = angle / (F::one() + F::one());
let s = half_angle.sin();
let c = half_angle.cos();
let len = (axis[0] * axis[0] + axis[1] * axis[1] + axis[2] * axis[2]).sqrt();
if len.is_zero() {
return Quaternion::identity();
}
let inv_len = F::one() / len;
Quaternion {
w: c,
x: axis[0] * inv_len * s,
y: axis[1] * inv_len * s,
z: axis[2] * inv_len * s,
}
}
pub fn from_euler_angles(roll: F, pitch: F, yaw: F) -> Self {
let half = F::one() / (F::one() + F::one());
let cy = (yaw * half).cos();
let sy = (yaw * half).sin();
let cp = (pitch * half).cos();
let sp = (pitch * half).sin();
let cr = (roll * half).cos();
let sr = (roll * half).sin();
Quaternion {
w: cr * cp * cy + sr * sp * sy,
x: sr * cp * cy - cr * sp * sy,
y: cr * sp * cy + sr * cp * sy,
z: cr * cp * sy - sr * sp * cy,
}
}
}