use na::{Quaternion, RealField, UnitQuaternion, Vector2, Vector3}; #[test] fn angle_2() { let a = Vector2::new(4.0, 0.0); let b = Vector2::new(9.0, 0.0); assert_eq!(a.angle(&b), 0.0); } #[test] fn angle_3() { let a = Vector3::new(4.0, 0.0, 0.5); let b = Vector3::new(8.0, 0.0, 1.0); assert_eq!(a.angle(&b), 0.0); } #[test] fn quaternion_euler_angles_issue_494() { let quat = UnitQuaternion::from_quaternion(Quaternion::new( -0.10405792, -0.6993922f32, -0.10406871, 0.69942284, )); let angs = quat.euler_angles(); assert_eq!(angs.0, 2.8461843); assert_eq!(angs.1, f32::frac_pi_2()); assert_eq!(angs.2, 0.0); } #[cfg(feature = "proptest-support")] mod proptest_tests { use na::{self, Rotation, Rotation2, Rotation3, Unit}; use simba::scalar::RealField; use std::f64; use crate::proptest::*; use proptest::{prop_assert, prop_assert_eq, proptest}; //creates N rotation planes and angles macro_rules! gen_rotation_planes { ($($v1:ident, $v2:ident),*) => { { //make an orthonormal basis let mut basis = [$($v1, $v2),*]; Vector::orthonormalize(&mut basis); let [$($v1, $v2),*] = basis; //"wedge" the vectors to make an arrary 2-blades representing rotation planes. [ //Since we start with vector pairs, each bivector is guaranteed to be simple $($v1.transpose().kronecker(&$v2) - $v2.transpose().kronecker(&$v1)),* ] } }; } macro_rules! gen_powf_rotation_test { ($( fn $powf_rot_n:ident($($v:ident in $vec:ident()),*); )*) => { proptest!{$( #[test] fn $powf_rot_n( $($v in $vec(),)* pow in PROPTEST_F64 ) { use nalgebra::*; //"wedge" the vectors to make an arrary 2-blades representing rotation planes. let mut bivectors = gen_rotation_planes!($($v),*); //condition the bivectors for b in &mut bivectors { if let Some((unit, norm)) = Unit::try_new_and_get(*b, 0.0) { //every component is duplicated once, so there's an extra factor of //sqrt(2) in the norm let mut angle = norm / 2.0f64.sqrt(); angle = na::wrap(angle, -f64::pi(), f64::pi()); *b = unit.into_inner() * angle * 2.0f64.sqrt(); } } let mut bivector = bivectors[0].clone(); for i in 1..bivectors.len() { bivector += bivectors[i]; } let r1 = Rotation::from_matrix_unchecked(bivector.exp()).powf(pow); let r2 = Rotation::from_matrix_unchecked((bivector * pow).exp()); prop_assert!(relative_eq!(r1, r2, epsilon=1e-7)); } )*} }; } macro_rules! gen_powf_180deg_rotation_test { ($( fn $powf_rot_n:ident($($v:ident in $vec:ident()),*); )*) => {$( proptest! { #[test] fn $powf_rot_n($($v in $vec(),)*) { use nalgebra::*; use num_traits::Zero; use std::f64::consts::PI; //an array of tuples with the unit plane and angle let plane_angles = gen_rotation_planes!($($v),*).iter().map( |b| Unit::try_new_and_get(*b,0.0).map_or_else( || (Matrix::zero(), 0.0), |(b,a)| (b.into_inner(), a) ) ).collect::>(); //loop over every choice of between the original angle and swapping to 180 deg let n = plane_angles.len(); for mask in 0..(1<