2016-12-05 05:44:42 +08:00
|
|
|
|
#[cfg(feature = "arbitrary")]
|
|
|
|
|
use quickcheck::{Arbitrary, Gen};
|
|
|
|
|
|
2021-03-02 19:25:12 +08:00
|
|
|
|
#[cfg(feature = "rand-no-std")]
|
2021-04-11 20:09:01 +08:00
|
|
|
|
use rand::{
|
|
|
|
|
distributions::{Distribution, Standard},
|
|
|
|
|
Rng,
|
|
|
|
|
};
|
2021-03-02 19:25:12 +08:00
|
|
|
|
|
2016-12-05 05:44:42 +08:00
|
|
|
|
use num::One;
|
|
|
|
|
use num_complex::Complex;
|
|
|
|
|
|
2019-03-23 21:29:07 +08:00
|
|
|
|
use crate::base::dimension::{U1, U2};
|
|
|
|
|
use crate::base::storage::Storage;
|
2021-03-06 00:08:46 +08:00
|
|
|
|
use crate::base::{Matrix2, Scalar, Unit, Vector, Vector2};
|
2019-03-23 21:29:07 +08:00
|
|
|
|
use crate::geometry::{Rotation2, UnitComplex};
|
2021-03-06 00:08:46 +08:00
|
|
|
|
use simba::scalar::{RealField, SupersetOf};
|
2020-03-22 06:22:55 +08:00
|
|
|
|
use simba::simd::SimdRealField;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
2020-11-21 18:56:24 +08:00
|
|
|
|
/// # Identity
|
2021-04-11 17:00:38 +08:00
|
|
|
|
impl<T: SimdRealField> UnitComplex<T>
|
2020-04-06 00:49:48 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
T::Element: SimdRealField,
|
2020-03-22 06:22:55 +08:00
|
|
|
|
{
|
2016-12-05 05:44:42 +08:00
|
|
|
|
/// The unit complex number multiplicative identity.
|
2018-11-05 17:34:58 +08:00
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
/// ```
|
|
|
|
|
/// # use nalgebra::UnitComplex;
|
|
|
|
|
/// let rot1 = UnitComplex::identity();
|
|
|
|
|
/// let rot2 = UnitComplex::new(1.7);
|
|
|
|
|
///
|
|
|
|
|
/// assert_eq!(rot1 * rot2, rot2);
|
|
|
|
|
/// assert_eq!(rot2 * rot1, rot2);
|
|
|
|
|
/// ```
|
2016-12-05 05:44:42 +08:00
|
|
|
|
#[inline]
|
|
|
|
|
pub fn identity() -> Self {
|
2021-04-11 17:00:38 +08:00
|
|
|
|
Self::new_unchecked(Complex::new(T::one(), T::zero()))
|
2016-12-05 05:44:42 +08:00
|
|
|
|
}
|
2020-11-21 18:56:24 +08:00
|
|
|
|
}
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
2020-11-21 18:56:24 +08:00
|
|
|
|
/// # Construction from a 2D rotation angle
|
2021-04-11 17:00:38 +08:00
|
|
|
|
impl<T: SimdRealField> UnitComplex<T>
|
2020-11-21 18:56:24 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
T::Element: SimdRealField,
|
2020-11-21 18:56:24 +08:00
|
|
|
|
{
|
2018-11-05 17:34:58 +08:00
|
|
|
|
/// Builds the unit complex number corresponding to the rotation with the given angle.
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// # #[macro_use] extern crate approx;
|
|
|
|
|
/// # use std::f32;
|
|
|
|
|
/// # use nalgebra::{UnitComplex, Point2};
|
|
|
|
|
/// let rot = UnitComplex::new(f32::consts::FRAC_PI_2);
|
|
|
|
|
///
|
|
|
|
|
/// assert_relative_eq!(rot * Point2::new(3.0, 4.0), Point2::new(-4.0, 3.0));
|
|
|
|
|
/// ```
|
2016-12-05 05:44:42 +08:00
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn new(angle: T) -> Self {
|
2020-03-22 06:22:55 +08:00
|
|
|
|
let (sin, cos) = angle.simd_sin_cos();
|
2017-08-03 01:37:44 +08:00
|
|
|
|
Self::from_cos_sin_unchecked(cos, sin)
|
2016-12-05 05:44:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Builds the unit complex number corresponding to the rotation with the angle.
|
|
|
|
|
///
|
|
|
|
|
/// Same as `Self::new(angle)`.
|
2018-11-05 17:34:58 +08:00
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// # #[macro_use] extern crate approx;
|
|
|
|
|
/// # use std::f32;
|
|
|
|
|
/// # use nalgebra::{UnitComplex, Point2};
|
|
|
|
|
/// let rot = UnitComplex::from_angle(f32::consts::FRAC_PI_2);
|
|
|
|
|
///
|
|
|
|
|
/// assert_relative_eq!(rot * Point2::new(3.0, 4.0), Point2::new(-4.0, 3.0));
|
|
|
|
|
/// ```
|
2020-11-15 23:57:49 +08:00
|
|
|
|
// TODO: deprecate this.
|
2016-12-05 05:44:42 +08:00
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn from_angle(angle: T) -> Self {
|
2016-12-05 05:44:42 +08:00
|
|
|
|
Self::new(angle)
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-24 12:48:42 +08:00
|
|
|
|
/// Builds the unit complex number from the sinus and cosinus of the rotation angle.
|
2017-08-03 01:37:44 +08:00
|
|
|
|
///
|
2018-11-05 17:34:58 +08:00
|
|
|
|
/// The input values are not checked to actually be cosines and sine of the same value.
|
|
|
|
|
/// Is is generally preferable to use the `::new(angle)` constructor instead.
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// # #[macro_use] extern crate approx;
|
|
|
|
|
/// # use std::f32;
|
|
|
|
|
/// # use nalgebra::{UnitComplex, Vector2, Point2};
|
|
|
|
|
/// let angle = f32::consts::FRAC_PI_2;
|
|
|
|
|
/// let rot = UnitComplex::from_cos_sin_unchecked(angle.cos(), angle.sin());
|
|
|
|
|
///
|
|
|
|
|
/// assert_relative_eq!(rot * Point2::new(3.0, 4.0), Point2::new(-4.0, 3.0));
|
|
|
|
|
/// ```
|
2017-08-03 01:37:44 +08:00
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn from_cos_sin_unchecked(cos: T, sin: T) -> Self {
|
2019-02-17 05:29:41 +08:00
|
|
|
|
Self::new_unchecked(Complex::new(cos, sin))
|
2017-08-03 01:37:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
2016-12-05 05:44:42 +08:00
|
|
|
|
/// Builds a unit complex rotation from an angle in radian wrapped in a 1-dimensional vector.
|
|
|
|
|
///
|
2018-11-05 17:34:58 +08:00
|
|
|
|
/// This is generally used in the context of generic programming. Using
|
|
|
|
|
/// the `::new(angle)` method instead is more common.
|
2016-12-05 05:44:42 +08:00
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn from_scaled_axis<SB: Storage<T, U1>>(axisangle: Vector<T, U1, SB>) -> Self {
|
2016-12-05 05:44:42 +08:00
|
|
|
|
Self::from_angle(axisangle[0])
|
|
|
|
|
}
|
2020-11-21 18:56:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// # Construction from an existing 2D matrix or complex number
|
2021-04-11 17:00:38 +08:00
|
|
|
|
impl<T: SimdRealField> UnitComplex<T>
|
2020-11-21 18:56:24 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
T::Element: SimdRealField,
|
2020-11-21 18:56:24 +08:00
|
|
|
|
{
|
2021-03-06 00:08:46 +08:00
|
|
|
|
/// Cast the components of `self` to another type.
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
/// ```
|
|
|
|
|
/// # use nalgebra::UnitComplex;
|
|
|
|
|
/// let c = UnitComplex::new(1.0f64);
|
|
|
|
|
/// let c2 = c.cast::<f32>();
|
|
|
|
|
/// assert_eq!(c2, UnitComplex::new(1.0f32));
|
|
|
|
|
/// ```
|
|
|
|
|
pub fn cast<To: Scalar>(self) -> UnitComplex<To>
|
|
|
|
|
where
|
|
|
|
|
UnitComplex<To>: SupersetOf<Self>,
|
|
|
|
|
{
|
|
|
|
|
crate::convert(self)
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-21 18:56:24 +08:00
|
|
|
|
/// The underlying complex number.
|
|
|
|
|
///
|
|
|
|
|
/// Same as `self.as_ref()`.
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
/// ```
|
|
|
|
|
/// # extern crate num_complex;
|
|
|
|
|
/// # use num_complex::Complex;
|
|
|
|
|
/// # use nalgebra::UnitComplex;
|
|
|
|
|
/// let angle = 1.78f32;
|
|
|
|
|
/// let rot = UnitComplex::new(angle);
|
|
|
|
|
/// assert_eq!(*rot.complex(), Complex::new(angle.cos(), angle.sin()));
|
|
|
|
|
/// ```
|
|
|
|
|
#[inline]
|
2021-06-07 22:34:03 +08:00
|
|
|
|
#[must_use]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn complex(&self) -> &Complex<T> {
|
2020-11-21 18:56:24 +08:00
|
|
|
|
self.as_ref()
|
|
|
|
|
}
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
|
|
|
|
/// Creates a new unit complex number from a complex number.
|
|
|
|
|
///
|
|
|
|
|
/// The input complex number will be normalized.
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn from_complex(q: Complex<T>) -> Self {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
Self::from_complex_and_get(q).0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Creates a new unit complex number from a complex number.
|
|
|
|
|
///
|
2018-11-05 17:34:58 +08:00
|
|
|
|
/// The input complex number will be normalized. Returns the norm of the complex number as well.
|
2017-08-03 01:37:44 +08:00
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn from_complex_and_get(q: Complex<T>) -> (Self, T) {
|
2020-03-22 06:22:55 +08:00
|
|
|
|
let norm = (q.im * q.im + q.re * q.re).simd_sqrt();
|
2017-08-03 01:37:44 +08:00
|
|
|
|
(Self::new_unchecked(q / norm), norm)
|
2016-12-05 05:44:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Builds the unit complex number from the corresponding 2D rotation matrix.
|
2018-11-05 17:34:58 +08:00
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
/// ```
|
|
|
|
|
/// # use nalgebra::{Rotation2, UnitComplex};
|
|
|
|
|
/// let rot = Rotation2::new(1.7);
|
|
|
|
|
/// let complex = UnitComplex::from_rotation_matrix(&rot);
|
|
|
|
|
/// assert_eq!(complex, UnitComplex::new(1.7));
|
|
|
|
|
/// ```
|
2020-11-15 23:57:49 +08:00
|
|
|
|
// TODO: add UnitComplex::from(...) instead?
|
2016-12-05 05:44:42 +08:00
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn from_rotation_matrix(rotmat: &Rotation2<T>) -> Self {
|
2016-12-05 05:44:42 +08:00
|
|
|
|
Self::new_unchecked(Complex::new(rotmat[(0, 0)], rotmat[(1, 0)]))
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-22 21:26:25 +08:00
|
|
|
|
/// Builds a rotation from a basis assumed to be orthonormal.
|
|
|
|
|
///
|
|
|
|
|
/// In order to get a valid unit-quaternion, the input must be an
|
|
|
|
|
/// orthonormal basis, i.e., all vectors are normalized, and the are
|
|
|
|
|
/// all orthogonal to each other. These invariants are not checked
|
|
|
|
|
/// by this method.
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn from_basis_unchecked(basis: &[Vector2<T>; 2]) -> Self {
|
2021-02-22 21:26:25 +08:00
|
|
|
|
let mat = Matrix2::from_columns(&basis[..]);
|
|
|
|
|
let rot = Rotation2::from_matrix_unchecked(mat);
|
|
|
|
|
Self::from_rotation_matrix(&rot)
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-19 05:41:46 +08:00
|
|
|
|
/// Builds an unit complex by extracting the rotation part of the given transformation `m`.
|
|
|
|
|
///
|
|
|
|
|
/// This is an iterative method. See `.from_matrix_eps` to provide mover
|
|
|
|
|
/// convergence parameters and starting solution.
|
|
|
|
|
/// This implements "A Robust Method to Extract the Rotational Part of Deformations" by Müller et al.
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn from_matrix(m: &Matrix2<T>) -> Self
|
2020-04-06 00:49:48 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
T: RealField,
|
2020-04-06 00:49:48 +08:00
|
|
|
|
{
|
2019-02-19 05:41:46 +08:00
|
|
|
|
Rotation2::from_matrix(m).into()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Builds an unit complex by extracting the rotation part of the given transformation `m`.
|
|
|
|
|
///
|
|
|
|
|
/// This implements "A Robust Method to Extract the Rotational Part of Deformations" by Müller et al.
|
|
|
|
|
///
|
|
|
|
|
/// # Parameters
|
|
|
|
|
///
|
|
|
|
|
/// * `m`: the matrix from which the rotational part is to be extracted.
|
|
|
|
|
/// * `eps`: the angular errors tolerated between the current rotation and the optimal one.
|
|
|
|
|
/// * `max_iter`: the maximum number of iterations. Loops indefinitely until convergence if set to `0`.
|
|
|
|
|
/// * `guess`: an estimate of the solution. Convergence will be significantly faster if an initial solution close
|
|
|
|
|
/// to the actual solution is provided. Can be set to `UnitQuaternion::identity()` if no other
|
|
|
|
|
/// guesses come to mind.
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn from_matrix_eps(m: &Matrix2<T>, eps: T, max_iter: usize, guess: Self) -> Self
|
2020-04-06 00:49:48 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
T: RealField,
|
2020-04-06 00:49:48 +08:00
|
|
|
|
{
|
2019-02-19 05:41:46 +08:00
|
|
|
|
let guess = Rotation2::from(guess);
|
|
|
|
|
Rotation2::from_matrix_eps(m, eps, max_iter, guess).into()
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-21 18:56:24 +08:00
|
|
|
|
/// The unit complex number needed to make `self` and `other` coincide.
|
|
|
|
|
///
|
|
|
|
|
/// The result is such that: `self.rotation_to(other) * self == other`.
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
/// ```
|
|
|
|
|
/// # #[macro_use] extern crate approx;
|
|
|
|
|
/// # use nalgebra::UnitComplex;
|
|
|
|
|
/// let rot1 = UnitComplex::new(0.1);
|
|
|
|
|
/// let rot2 = UnitComplex::new(1.7);
|
|
|
|
|
/// let rot_to = rot1.rotation_to(&rot2);
|
|
|
|
|
///
|
|
|
|
|
/// assert_relative_eq!(rot_to * rot1, rot2);
|
|
|
|
|
/// assert_relative_eq!(rot_to.inverse() * rot2, rot1);
|
|
|
|
|
/// ```
|
|
|
|
|
#[inline]
|
2021-06-07 22:34:03 +08:00
|
|
|
|
#[must_use]
|
2020-11-21 18:56:24 +08:00
|
|
|
|
pub fn rotation_to(&self, other: &Self) -> Self {
|
|
|
|
|
other / self
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Raise this unit complex number to a given floating power.
|
|
|
|
|
///
|
|
|
|
|
/// This returns the unit complex number that identifies a rotation angle equal to
|
|
|
|
|
/// `self.angle() × n`.
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
/// ```
|
|
|
|
|
/// # #[macro_use] extern crate approx;
|
|
|
|
|
/// # use nalgebra::UnitComplex;
|
|
|
|
|
/// let rot = UnitComplex::new(0.78);
|
|
|
|
|
/// let pow = rot.powf(2.0);
|
|
|
|
|
/// assert_relative_eq!(pow.angle(), 2.0 * 0.78);
|
|
|
|
|
/// ```
|
|
|
|
|
#[inline]
|
2021-06-07 22:34:03 +08:00
|
|
|
|
#[must_use]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn powf(&self, n: T) -> Self {
|
2020-11-21 18:56:24 +08:00
|
|
|
|
Self::from_angle(self.angle() * n)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// # Construction from two vectors
|
2021-04-11 17:00:38 +08:00
|
|
|
|
impl<T: SimdRealField> UnitComplex<T>
|
2020-11-21 18:56:24 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
T::Element: SimdRealField,
|
2020-11-21 18:56:24 +08:00
|
|
|
|
{
|
2016-12-05 05:44:42 +08:00
|
|
|
|
/// The unit complex needed to make `a` and `b` be collinear and point toward the same
|
|
|
|
|
/// direction.
|
2018-11-05 17:34:58 +08:00
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
/// ```
|
|
|
|
|
/// # #[macro_use] extern crate approx;
|
|
|
|
|
/// # use nalgebra::{Vector2, UnitComplex};
|
|
|
|
|
/// let a = Vector2::new(1.0, 2.0);
|
|
|
|
|
/// let b = Vector2::new(2.0, 1.0);
|
|
|
|
|
/// let rot = UnitComplex::rotation_between(&a, &b);
|
|
|
|
|
/// assert_relative_eq!(rot * a, b);
|
|
|
|
|
/// assert_relative_eq!(rot.inverse() * b, a);
|
|
|
|
|
/// ```
|
2016-12-05 05:44:42 +08:00
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn rotation_between<SB, SC>(a: &Vector<T, U2, SB>, b: &Vector<T, U2, SC>) -> Self
|
2018-02-02 19:26:35 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
T: RealField,
|
|
|
|
|
SB: Storage<T, U2>,
|
|
|
|
|
SC: Storage<T, U2>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
{
|
2021-04-11 17:00:38 +08:00
|
|
|
|
Self::scaled_rotation_between(a, b, T::one())
|
2016-12-05 05:44:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// The smallest rotation needed to make `a` and `b` collinear and point toward the same
|
|
|
|
|
/// direction, raised to the power `s`.
|
2018-11-05 17:34:58 +08:00
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
/// ```
|
|
|
|
|
/// # #[macro_use] extern crate approx;
|
|
|
|
|
/// # use nalgebra::{Vector2, UnitComplex};
|
|
|
|
|
/// let a = Vector2::new(1.0, 2.0);
|
|
|
|
|
/// let b = Vector2::new(2.0, 1.0);
|
|
|
|
|
/// let rot2 = UnitComplex::scaled_rotation_between(&a, &b, 0.2);
|
|
|
|
|
/// let rot5 = UnitComplex::scaled_rotation_between(&a, &b, 0.5);
|
|
|
|
|
/// assert_relative_eq!(rot2 * rot2 * rot2 * rot2 * rot2 * a, b, epsilon = 1.0e-6);
|
|
|
|
|
/// assert_relative_eq!(rot5 * rot5 * a, b, epsilon = 1.0e-6);
|
|
|
|
|
/// ```
|
2016-12-05 05:44:42 +08:00
|
|
|
|
#[inline]
|
2018-02-02 19:26:35 +08:00
|
|
|
|
pub fn scaled_rotation_between<SB, SC>(
|
2021-04-11 17:00:38 +08:00
|
|
|
|
a: &Vector<T, U2, SB>,
|
|
|
|
|
b: &Vector<T, U2, SC>,
|
|
|
|
|
s: T,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
) -> Self
|
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
T: RealField,
|
|
|
|
|
SB: Storage<T, U2>,
|
|
|
|
|
SC: Storage<T, U2>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
{
|
2020-11-15 23:57:49 +08:00
|
|
|
|
// TODO: code duplication with Rotation.
|
2018-03-09 00:30:59 +08:00
|
|
|
|
if let (Some(na), Some(nb)) = (
|
2021-04-11 17:00:38 +08:00
|
|
|
|
Unit::try_new(a.clone_owned(), T::zero()),
|
|
|
|
|
Unit::try_new(b.clone_owned(), T::zero()),
|
2018-03-09 00:30:59 +08:00
|
|
|
|
) {
|
|
|
|
|
Self::scaled_rotation_between_axis(&na, &nb, s)
|
2018-02-02 19:26:35 +08:00
|
|
|
|
} else {
|
2016-12-05 05:44:42 +08:00
|
|
|
|
Self::identity()
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-03-09 00:30:59 +08:00
|
|
|
|
|
|
|
|
|
/// The unit complex needed to make `a` and `b` be collinear and point toward the same
|
|
|
|
|
/// direction.
|
2018-11-05 17:34:58 +08:00
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
/// ```
|
|
|
|
|
/// # #[macro_use] extern crate approx;
|
|
|
|
|
/// # use nalgebra::{Unit, Vector2, UnitComplex};
|
|
|
|
|
/// let a = Unit::new_normalize(Vector2::new(1.0, 2.0));
|
|
|
|
|
/// let b = Unit::new_normalize(Vector2::new(2.0, 1.0));
|
|
|
|
|
/// let rot = UnitComplex::rotation_between_axis(&a, &b);
|
|
|
|
|
/// assert_relative_eq!(rot * a, b);
|
|
|
|
|
/// assert_relative_eq!(rot.inverse() * b, a);
|
|
|
|
|
/// ```
|
2018-03-09 00:30:59 +08:00
|
|
|
|
#[inline]
|
|
|
|
|
pub fn rotation_between_axis<SB, SC>(
|
2021-04-11 17:00:38 +08:00
|
|
|
|
a: &Unit<Vector<T, U2, SB>>,
|
|
|
|
|
b: &Unit<Vector<T, U2, SC>>,
|
2018-03-09 00:30:59 +08:00
|
|
|
|
) -> Self
|
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
SB: Storage<T, U2>,
|
|
|
|
|
SC: Storage<T, U2>,
|
2018-03-09 00:30:59 +08:00
|
|
|
|
{
|
2021-04-11 17:00:38 +08:00
|
|
|
|
Self::scaled_rotation_between_axis(a, b, T::one())
|
2018-03-09 00:30:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// The smallest rotation needed to make `a` and `b` collinear and point toward the same
|
|
|
|
|
/// direction, raised to the power `s`.
|
2018-11-05 17:34:58 +08:00
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
/// ```
|
|
|
|
|
/// # #[macro_use] extern crate approx;
|
|
|
|
|
/// # use nalgebra::{Unit, Vector2, UnitComplex};
|
|
|
|
|
/// let a = Unit::new_normalize(Vector2::new(1.0, 2.0));
|
|
|
|
|
/// let b = Unit::new_normalize(Vector2::new(2.0, 1.0));
|
|
|
|
|
/// let rot2 = UnitComplex::scaled_rotation_between_axis(&a, &b, 0.2);
|
|
|
|
|
/// let rot5 = UnitComplex::scaled_rotation_between_axis(&a, &b, 0.5);
|
|
|
|
|
/// assert_relative_eq!(rot2 * rot2 * rot2 * rot2 * rot2 * a, b, epsilon = 1.0e-6);
|
|
|
|
|
/// assert_relative_eq!(rot5 * rot5 * a, b, epsilon = 1.0e-6);
|
|
|
|
|
/// ```
|
2018-03-09 00:30:59 +08:00
|
|
|
|
#[inline]
|
|
|
|
|
pub fn scaled_rotation_between_axis<SB, SC>(
|
2021-04-11 17:00:38 +08:00
|
|
|
|
na: &Unit<Vector<T, U2, SB>>,
|
|
|
|
|
nb: &Unit<Vector<T, U2, SC>>,
|
|
|
|
|
s: T,
|
2018-03-09 00:30:59 +08:00
|
|
|
|
) -> Self
|
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
SB: Storage<T, U2>,
|
|
|
|
|
SC: Storage<T, U2>,
|
2018-03-09 00:30:59 +08:00
|
|
|
|
{
|
|
|
|
|
let sang = na.perp(&nb);
|
|
|
|
|
let cang = na.dot(&nb);
|
|
|
|
|
|
2020-03-22 06:22:55 +08:00
|
|
|
|
Self::from_angle(sang.simd_atan2(cang) * s)
|
2018-03-09 00:30:59 +08:00
|
|
|
|
}
|
2016-12-05 05:44:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-11 17:00:38 +08:00
|
|
|
|
impl<T: SimdRealField> One for UnitComplex<T>
|
2020-04-06 00:49:48 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
T::Element: SimdRealField,
|
2020-03-22 06:22:55 +08:00
|
|
|
|
{
|
2016-12-05 05:44:42 +08:00
|
|
|
|
#[inline]
|
|
|
|
|
fn one() -> Self {
|
|
|
|
|
Self::identity()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-12 18:14:16 +08:00
|
|
|
|
#[cfg(feature = "rand")]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
impl<T: SimdRealField> Distribution<UnitComplex<T>> for Standard
|
2020-03-22 06:22:55 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
T::Element: SimdRealField,
|
|
|
|
|
rand_distr::UnitCircle: Distribution<[T; 2]>,
|
2018-05-23 05:58:14 +08:00
|
|
|
|
{
|
2018-07-08 07:03:08 +08:00
|
|
|
|
/// Generate a uniformly distributed random `UnitComplex`.
|
2016-12-05 05:44:42 +08:00
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
fn sample<'a, R: Rng + ?Sized>(&self, rng: &mut R) -> UnitComplex<T> {
|
2021-04-10 14:49:46 +08:00
|
|
|
|
let x = rng.sample(rand_distr::UnitCircle);
|
|
|
|
|
UnitComplex::new_unchecked(Complex::new(x[0], x[1]))
|
2016-12-05 05:44:42 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-02 19:26:35 +08:00
|
|
|
|
#[cfg(feature = "arbitrary")]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
impl<T: SimdRealField + Arbitrary> Arbitrary for UnitComplex<T>
|
2020-04-06 00:49:48 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
T::Element: SimdRealField,
|
2020-03-22 06:22:55 +08:00
|
|
|
|
{
|
2016-12-05 05:44:42 +08:00
|
|
|
|
#[inline]
|
2021-03-01 00:52:14 +08:00
|
|
|
|
fn arbitrary(g: &mut Gen) -> Self {
|
2021-04-11 17:00:38 +08:00
|
|
|
|
UnitComplex::from_angle(T::arbitrary(g))
|
2016-12-05 05:44:42 +08:00
|
|
|
|
}
|
|
|
|
|
}
|