1 #[cfg(feature = "arbitrary")] 2 use quickcheck::{Arbitrary, Gen}; 3 4 use num::One; 5 use num_complex::Complex; 6 use rand::distributions::{Distribution, OpenClosed01, Standard}; 7 use rand::Rng; 8 9 use alga::general::RealField; 10 use crate::base::dimension::{U1, U2}; 11 use crate::base::storage::Storage; 12 use crate::base::{Unit, Vector, Matrix2}; 13 use crate::geometry::{Rotation2, UnitComplex}; 14 15 impl<N: RealField> UnitComplex<N> { 16 /// The unit complex number multiplicative identity. 17 /// 18 /// # Example 19 /// ``` 20 /// # use nalgebra::UnitComplex; 21 /// let rot1 = UnitComplex::identity(); 22 /// let rot2 = UnitComplex::new(1.7); 23 /// 24 /// assert_eq!(rot1 * rot2, rot2); 25 /// assert_eq!(rot2 * rot1, rot2); 26 /// ``` 27 #[inline] identity() -> Self28 pub fn identity() -> Self { 29 Self::new_unchecked(Complex::new(N::one(), N::zero())) 30 } 31 32 /// Builds the unit complex number corresponding to the rotation with the given angle. 33 /// 34 /// # Example 35 /// 36 /// ``` 37 /// # #[macro_use] extern crate approx; 38 /// # use std::f32; 39 /// # use nalgebra::{UnitComplex, Point2}; 40 /// let rot = UnitComplex::new(f32::consts::FRAC_PI_2); 41 /// 42 /// assert_relative_eq!(rot * Point2::new(3.0, 4.0), Point2::new(-4.0, 3.0)); 43 /// ``` 44 #[inline] new(angle: N) -> Self45 pub fn new(angle: N) -> Self { 46 let (sin, cos) = angle.sin_cos(); 47 Self::from_cos_sin_unchecked(cos, sin) 48 } 49 50 /// Builds the unit complex number corresponding to the rotation with the angle. 51 /// 52 /// Same as `Self::new(angle)`. 53 /// 54 /// # Example 55 /// 56 /// ``` 57 /// # #[macro_use] extern crate approx; 58 /// # use std::f32; 59 /// # use nalgebra::{UnitComplex, Point2}; 60 /// let rot = UnitComplex::from_angle(f32::consts::FRAC_PI_2); 61 /// 62 /// assert_relative_eq!(rot * Point2::new(3.0, 4.0), Point2::new(-4.0, 3.0)); 63 /// ``` 64 // FIXME: deprecate this. 65 #[inline] from_angle(angle: N) -> Self66 pub fn from_angle(angle: N) -> Self { 67 Self::new(angle) 68 } 69 70 /// Builds the unit complex number from the sinus and cosinus of the rotation angle. 71 /// 72 /// The input values are not checked to actually be cosines and sine of the same value. 73 /// Is is generally preferable to use the `::new(angle)` constructor instead. 74 /// 75 /// # Example 76 /// 77 /// ``` 78 /// # #[macro_use] extern crate approx; 79 /// # use std::f32; 80 /// # use nalgebra::{UnitComplex, Vector2, Point2}; 81 /// let angle = f32::consts::FRAC_PI_2; 82 /// let rot = UnitComplex::from_cos_sin_unchecked(angle.cos(), angle.sin()); 83 /// 84 /// assert_relative_eq!(rot * Point2::new(3.0, 4.0), Point2::new(-4.0, 3.0)); 85 /// ``` 86 #[inline] from_cos_sin_unchecked(cos: N, sin: N) -> Self87 pub fn from_cos_sin_unchecked(cos: N, sin: N) -> Self { 88 Self::new_unchecked(Complex::new(cos, sin)) 89 } 90 91 /// Builds a unit complex rotation from an angle in radian wrapped in a 1-dimensional vector. 92 /// 93 /// This is generally used in the context of generic programming. Using 94 /// the `::new(angle)` method instead is more common. 95 #[inline] from_scaled_axis<SB: Storage<N, U1>>(axisangle: Vector<N, U1, SB>) -> Self96 pub fn from_scaled_axis<SB: Storage<N, U1>>(axisangle: Vector<N, U1, SB>) -> Self { 97 Self::from_angle(axisangle[0]) 98 } 99 100 /// Creates a new unit complex number from a complex number. 101 /// 102 /// The input complex number will be normalized. 103 #[inline] from_complex(q: Complex<N>) -> Self104 pub fn from_complex(q: Complex<N>) -> Self { 105 Self::from_complex_and_get(q).0 106 } 107 108 /// Creates a new unit complex number from a complex number. 109 /// 110 /// The input complex number will be normalized. Returns the norm of the complex number as well. 111 #[inline] from_complex_and_get(q: Complex<N>) -> (Self, N)112 pub fn from_complex_and_get(q: Complex<N>) -> (Self, N) { 113 let norm = (q.im * q.im + q.re * q.re).sqrt(); 114 (Self::new_unchecked(q / norm), norm) 115 } 116 117 /// Builds the unit complex number from the corresponding 2D rotation matrix. 118 /// 119 /// # Example 120 /// ``` 121 /// # use nalgebra::{Rotation2, UnitComplex}; 122 /// let rot = Rotation2::new(1.7); 123 /// let complex = UnitComplex::from_rotation_matrix(&rot); 124 /// assert_eq!(complex, UnitComplex::new(1.7)); 125 /// ``` 126 // FIXME: add UnitComplex::from(...) instead? 127 #[inline] from_rotation_matrix(rotmat: &Rotation2<N>) -> Self128 pub fn from_rotation_matrix(rotmat: &Rotation2<N>) -> Self { 129 Self::new_unchecked(Complex::new(rotmat[(0, 0)], rotmat[(1, 0)])) 130 } 131 132 /// Builds an unit complex by extracting the rotation part of the given transformation `m`. 133 /// 134 /// This is an iterative method. See `.from_matrix_eps` to provide mover 135 /// convergence parameters and starting solution. 136 /// This implements "A Robust Method to Extract the Rotational Part of Deformations" by Müller et al. from_matrix(m: &Matrix2<N>) -> Self137 pub fn from_matrix(m: &Matrix2<N>) -> Self { 138 Rotation2::from_matrix(m).into() 139 } 140 141 /// Builds an unit complex by extracting the rotation part of the given transformation `m`. 142 /// 143 /// This implements "A Robust Method to Extract the Rotational Part of Deformations" by Müller et al. 144 /// 145 /// # Parameters 146 /// 147 /// * `m`: the matrix from which the rotational part is to be extracted. 148 /// * `eps`: the angular errors tolerated between the current rotation and the optimal one. 149 /// * `max_iter`: the maximum number of iterations. Loops indefinitely until convergence if set to `0`. 150 /// * `guess`: an estimate of the solution. Convergence will be significantly faster if an initial solution close 151 /// to the actual solution is provided. Can be set to `UnitQuaternion::identity()` if no other 152 /// guesses come to mind. from_matrix_eps(m: &Matrix2<N>, eps: N, max_iter: usize, guess: Self) -> Self153 pub fn from_matrix_eps(m: &Matrix2<N>, eps: N, max_iter: usize, guess: Self) -> Self { 154 let guess = Rotation2::from(guess); 155 Rotation2::from_matrix_eps(m, eps, max_iter, guess).into() 156 } 157 158 /// The unit complex needed to make `a` and `b` be collinear and point toward the same 159 /// direction. 160 /// 161 /// # Example 162 /// ``` 163 /// # #[macro_use] extern crate approx; 164 /// # use nalgebra::{Vector2, UnitComplex}; 165 /// let a = Vector2::new(1.0, 2.0); 166 /// let b = Vector2::new(2.0, 1.0); 167 /// let rot = UnitComplex::rotation_between(&a, &b); 168 /// assert_relative_eq!(rot * a, b); 169 /// assert_relative_eq!(rot.inverse() * b, a); 170 /// ``` 171 #[inline] rotation_between<SB, SC>(a: &Vector<N, U2, SB>, b: &Vector<N, U2, SC>) -> Self where SB: Storage<N, U2>, SC: Storage<N, U2>,172 pub fn rotation_between<SB, SC>(a: &Vector<N, U2, SB>, b: &Vector<N, U2, SC>) -> Self 173 where 174 SB: Storage<N, U2>, 175 SC: Storage<N, U2>, 176 { 177 Self::scaled_rotation_between(a, b, N::one()) 178 } 179 180 /// The smallest rotation needed to make `a` and `b` collinear and point toward the same 181 /// direction, raised to the power `s`. 182 /// 183 /// # Example 184 /// ``` 185 /// # #[macro_use] extern crate approx; 186 /// # use nalgebra::{Vector2, UnitComplex}; 187 /// let a = Vector2::new(1.0, 2.0); 188 /// let b = Vector2::new(2.0, 1.0); 189 /// let rot2 = UnitComplex::scaled_rotation_between(&a, &b, 0.2); 190 /// let rot5 = UnitComplex::scaled_rotation_between(&a, &b, 0.5); 191 /// assert_relative_eq!(rot2 * rot2 * rot2 * rot2 * rot2 * a, b, epsilon = 1.0e-6); 192 /// assert_relative_eq!(rot5 * rot5 * a, b, epsilon = 1.0e-6); 193 /// ``` 194 #[inline] scaled_rotation_between<SB, SC>( a: &Vector<N, U2, SB>, b: &Vector<N, U2, SC>, s: N, ) -> Self where SB: Storage<N, U2>, SC: Storage<N, U2>,195 pub fn scaled_rotation_between<SB, SC>( 196 a: &Vector<N, U2, SB>, 197 b: &Vector<N, U2, SC>, 198 s: N, 199 ) -> Self 200 where 201 SB: Storage<N, U2>, 202 SC: Storage<N, U2>, 203 { 204 // FIXME: code duplication with Rotation. 205 if let (Some(na), Some(nb)) = ( 206 Unit::try_new(a.clone_owned(), N::zero()), 207 Unit::try_new(b.clone_owned(), N::zero()), 208 ) { 209 Self::scaled_rotation_between_axis(&na, &nb, s) 210 } else { 211 Self::identity() 212 } 213 } 214 215 /// The unit complex needed to make `a` and `b` be collinear and point toward the same 216 /// direction. 217 /// 218 /// # Example 219 /// ``` 220 /// # #[macro_use] extern crate approx; 221 /// # use nalgebra::{Unit, Vector2, UnitComplex}; 222 /// let a = Unit::new_normalize(Vector2::new(1.0, 2.0)); 223 /// let b = Unit::new_normalize(Vector2::new(2.0, 1.0)); 224 /// let rot = UnitComplex::rotation_between_axis(&a, &b); 225 /// assert_relative_eq!(rot * a, b); 226 /// assert_relative_eq!(rot.inverse() * b, a); 227 /// ``` 228 #[inline] rotation_between_axis<SB, SC>( a: &Unit<Vector<N, U2, SB>>, b: &Unit<Vector<N, U2, SC>>, ) -> Self where SB: Storage<N, U2>, SC: Storage<N, U2>,229 pub fn rotation_between_axis<SB, SC>( 230 a: &Unit<Vector<N, U2, SB>>, 231 b: &Unit<Vector<N, U2, SC>>, 232 ) -> Self 233 where 234 SB: Storage<N, U2>, 235 SC: Storage<N, U2>, 236 { 237 Self::scaled_rotation_between_axis(a, b, N::one()) 238 } 239 240 /// The smallest rotation needed to make `a` and `b` collinear and point toward the same 241 /// direction, raised to the power `s`. 242 /// 243 /// # Example 244 /// ``` 245 /// # #[macro_use] extern crate approx; 246 /// # use nalgebra::{Unit, Vector2, UnitComplex}; 247 /// let a = Unit::new_normalize(Vector2::new(1.0, 2.0)); 248 /// let b = Unit::new_normalize(Vector2::new(2.0, 1.0)); 249 /// let rot2 = UnitComplex::scaled_rotation_between_axis(&a, &b, 0.2); 250 /// let rot5 = UnitComplex::scaled_rotation_between_axis(&a, &b, 0.5); 251 /// assert_relative_eq!(rot2 * rot2 * rot2 * rot2 * rot2 * a, b, epsilon = 1.0e-6); 252 /// assert_relative_eq!(rot5 * rot5 * a, b, epsilon = 1.0e-6); 253 /// ``` 254 #[inline] scaled_rotation_between_axis<SB, SC>( na: &Unit<Vector<N, U2, SB>>, nb: &Unit<Vector<N, U2, SC>>, s: N, ) -> Self where SB: Storage<N, U2>, SC: Storage<N, U2>,255 pub fn scaled_rotation_between_axis<SB, SC>( 256 na: &Unit<Vector<N, U2, SB>>, 257 nb: &Unit<Vector<N, U2, SC>>, 258 s: N, 259 ) -> Self 260 where 261 SB: Storage<N, U2>, 262 SC: Storage<N, U2>, 263 { 264 let sang = na.perp(&nb); 265 let cang = na.dot(&nb); 266 267 Self::from_angle(sang.atan2(cang) * s) 268 } 269 } 270 271 impl<N: RealField> One for UnitComplex<N> { 272 #[inline] one() -> Self273 fn one() -> Self { 274 Self::identity() 275 } 276 } 277 278 impl<N: RealField> Distribution<UnitComplex<N>> for Standard 279 where OpenClosed01: Distribution<N> 280 { 281 /// Generate a uniformly distributed random `UnitComplex`. 282 #[inline] sample<'a, R: Rng + ?Sized>(&self, rng: &mut R) -> UnitComplex<N>283 fn sample<'a, R: Rng + ?Sized>(&self, rng: &mut R) -> UnitComplex<N> { 284 UnitComplex::from_angle(rng.sample(OpenClosed01) * N::two_pi()) 285 } 286 } 287 288 #[cfg(feature = "arbitrary")] 289 impl<N: RealField + Arbitrary> Arbitrary for UnitComplex<N> { 290 #[inline] arbitrary<G: Gen>(g: &mut G) -> Self291 fn arbitrary<G: Gen>(g: &mut G) -> Self { 292 UnitComplex::from_angle(N::arbitrary(g)) 293 } 294 } 295