use nalgebra::{Matrix3, Vector3, Vector4};
use std::fmt;
pub use strum::IntoEnumIterator;
use strum_macros::EnumIter;
pub(crate) const ATTITUDE_EPSILON: f64 = 1.0e-12;
#[derive(Clone, Copy)]
pub struct Quaternion {
pub(crate) data: Vector4<f64>,
}
#[derive(Clone, Copy)]
pub struct EulerAxis {
pub axis: Vector3<f64>,
pub angle: f64,
}
#[derive(Clone, Copy, PartialEq, EnumIter)]
pub enum EulerAngleOrder {
XYX = 121,
XYZ = 123,
XZX = 131,
XZY = 132,
YXY = 212,
YXZ = 213,
YZX = 231,
YZY = 232,
ZXY = 312,
ZXZ = 313,
ZYX = 321,
ZYZ = 323,
}
impl fmt::Display for EulerAngleOrder {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
EulerAngleOrder::XYX => write!(f, "121"),
EulerAngleOrder::XYZ => write!(f, "123"),
EulerAngleOrder::XZX => write!(f, "131"),
EulerAngleOrder::XZY => write!(f, "132"),
EulerAngleOrder::YXY => write!(f, "212"),
EulerAngleOrder::YXZ => write!(f, "213"),
EulerAngleOrder::YZX => write!(f, "231"),
EulerAngleOrder::YZY => write!(f, "232"),
EulerAngleOrder::ZXY => write!(f, "312"),
EulerAngleOrder::ZXZ => write!(f, "313"),
EulerAngleOrder::ZYX => write!(f, "321"),
EulerAngleOrder::ZYZ => write!(f, "323"),
}
}
}
impl fmt::Debug for EulerAngleOrder {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
EulerAngleOrder::XYX => write!(f, "XYX::121"),
EulerAngleOrder::XYZ => write!(f, "XYZ::123"),
EulerAngleOrder::XZX => write!(f, "XZX::131"),
EulerAngleOrder::XZY => write!(f, "XZY::132"),
EulerAngleOrder::YXY => write!(f, "YXY::212"),
EulerAngleOrder::YXZ => write!(f, "YXZ::213"),
EulerAngleOrder::YZX => write!(f, "YZX::231"),
EulerAngleOrder::YZY => write!(f, "YZY::232"),
EulerAngleOrder::ZXY => write!(f, "ZXY::312"),
EulerAngleOrder::ZXZ => write!(f, "ZXZ::313"),
EulerAngleOrder::ZYX => write!(f, "ZYX::321"),
EulerAngleOrder::ZYZ => write!(f, "ZYZ::323"),
}
}
}
#[derive(Clone, Copy)]
pub struct EulerAngle {
pub order: EulerAngleOrder,
pub phi: f64,
pub theta: f64,
pub psi: f64,
}
#[derive(Clone, Copy)]
pub struct RotationMatrix {
pub(crate) data: crate::math::SMatrix3,
}
#[cfg(test)]
#[cfg_attr(coverage_nightly, coverage(off))]
mod tests {
use super::*;
#[test]
fn test_euler_angle_order_display() {
assert_eq!(format!("{}", EulerAngleOrder::XYX), "121");
assert_eq!(format!("{}", EulerAngleOrder::XYZ), "123");
assert_eq!(format!("{}", EulerAngleOrder::XZX), "131");
assert_eq!(format!("{}", EulerAngleOrder::XZY), "132");
assert_eq!(format!("{}", EulerAngleOrder::YXY), "212");
assert_eq!(format!("{}", EulerAngleOrder::YXZ), "213");
assert_eq!(format!("{}", EulerAngleOrder::YZX), "231");
assert_eq!(format!("{}", EulerAngleOrder::YZY), "232");
assert_eq!(format!("{}", EulerAngleOrder::ZXY), "312");
assert_eq!(format!("{}", EulerAngleOrder::ZXZ), "313");
assert_eq!(format!("{}", EulerAngleOrder::ZYX), "321");
assert_eq!(format!("{}", EulerAngleOrder::ZYZ), "323");
}
#[test]
fn test_euler_angle_order_debug() {
assert_eq!(format!("{:?}", EulerAngleOrder::XYX), "XYX::121");
assert_eq!(format!("{:?}", EulerAngleOrder::XYZ), "XYZ::123");
assert_eq!(format!("{:?}", EulerAngleOrder::XZX), "XZX::131");
assert_eq!(format!("{:?}", EulerAngleOrder::XZY), "XZY::132");
assert_eq!(format!("{:?}", EulerAngleOrder::YXY), "YXY::212");
assert_eq!(format!("{:?}", EulerAngleOrder::YXZ), "YXZ::213");
assert_eq!(format!("{:?}", EulerAngleOrder::YZX), "YZX::231");
assert_eq!(format!("{:?}", EulerAngleOrder::YZY), "YZY::232");
assert_eq!(format!("{:?}", EulerAngleOrder::ZXY), "ZXY::312");
assert_eq!(format!("{:?}", EulerAngleOrder::ZXZ), "ZXZ::313");
assert_eq!(format!("{:?}", EulerAngleOrder::ZYX), "ZYX::321");
assert_eq!(format!("{:?}", EulerAngleOrder::ZYZ), "ZYZ::323");
}
#[test]
fn test_euler_angle_order_iter() {
let all_orders: Vec<EulerAngleOrder> = EulerAngleOrder::iter().collect();
assert_eq!(all_orders.len(), 12);
assert!(all_orders.contains(&EulerAngleOrder::XYX));
assert!(all_orders.contains(&EulerAngleOrder::XYZ));
assert!(all_orders.contains(&EulerAngleOrder::XZX));
assert!(all_orders.contains(&EulerAngleOrder::XZY));
assert!(all_orders.contains(&EulerAngleOrder::YXY));
assert!(all_orders.contains(&EulerAngleOrder::YXZ));
assert!(all_orders.contains(&EulerAngleOrder::YZX));
assert!(all_orders.contains(&EulerAngleOrder::YZY));
assert!(all_orders.contains(&EulerAngleOrder::ZXY));
assert!(all_orders.contains(&EulerAngleOrder::ZXZ));
assert!(all_orders.contains(&EulerAngleOrder::ZYX));
assert!(all_orders.contains(&EulerAngleOrder::ZYZ));
}
}