// Copyright 2013 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms.
use core::cmp::{Eq, PartialEq}; use core::hash::Hash; use core::iter::Sum; use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, Sub, SubAssign};
#[cfg(feature = "bytemuck")] use bytemuck::{Pod, Zeroable}; #[cfg(feature = "malloc_size_of")] use malloc_size_of::{MallocSizeOf, MallocSizeOfOps}; use num_traits::real::Real; use num_traits::{Float, FloatConst, NumCast, One, Zero}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize};
#[cfg(feature = "bytemuck")] unsafeimpl<T: Zeroable> Zeroable for Angle<T> {}
#[cfg(feature = "bytemuck")] unsafeimpl<T: Pod> Pod for Angle<T> {}
#[cfg(feature = "arbitrary")] impl<'a, T> arbitrary::Arbitrary<'a> for Angle<T> where
T: arbitrary::Arbitrary<'a>,
{ // This implementation could be derived, but the derive would require an `extern crate std`. fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
Ok(Angle {
radians: arbitrary::Arbitrary::arbitrary(u)?,
})
}
#[inline] pubfn to_degrees(self) -> T {
T::radians_to_degrees(self.radians)
}
}
impl<T> Angle<T> where
T: Rem<Output = T> + Sub<Output = T> + Add<Output = T> + Zero + FloatConst + PartialOrd + Copy,
{ /// Returns this angle in the [0..2*PI[ range. pubfn positive(&self) -> Self { let two_pi = T::PI() + T::PI(); letmut a = self.radians % two_pi; if a < T::zero() {
a = a + two_pi;
}
Angle::radians(a)
}
/// Returns this angle in the ]-PI..PI] range. pubfn signed(&self) -> Self {
Angle::pi() - (Angle::pi() - *self).positive()
}
}
impl<T> Angle<T> where
T: Rem<Output = T>
+ Mul<Output = T>
+ Sub<Output = T>
+ Add<Output = T>
+ One
+ FloatConst
+ Copy,
{ /// Returns the shortest signed angle between two angles. /// /// Takes wrapping and signs into account. pubfn angle_to(&self, to: Self) -> Self { let two = T::one() + T::one(); let max = T::PI() * two; let d = (to.radians - self.radians) % max;
Angle::radians(two * d % max - d)
}
/// Linear interpolation between two angles, using the shortest path. pubfn lerp(&self, other: Self, t: T) -> Self {
*self + self.angle_to(other) * t
}
}
impl<T> Angle<T> where
T: Float,
{ /// Returns `true` if the angle is a finite number. #[inline] pubfn is_finite(self) -> bool { self.radians.is_finite()
}
}
let a = A::radians(1.0); let b = A::radians(2.0);
assert!(a.lerp(b, 0.25).approx_eq(&Angle::radians(1.25)));
assert!(a.lerp(b, 0.5).approx_eq(&Angle::radians(1.5)));
assert!(a.lerp(b, 0.75).approx_eq(&Angle::radians(1.75)));
assert!(a
.lerp(b + A::two_pi(), 0.75)
.approx_eq(&Angle::radians(1.75)));
assert!(a
.lerp(b - A::two_pi(), 0.75)
.approx_eq(&Angle::radians(1.75)));
assert!(a
.lerp(b + A::two_pi() * 5.0, 0.75)
.approx_eq(&Angle::radians(1.75)));
}
#[test] fn sum() { type A = Angle<f32>; let angles = [A::radians(1.0), A::radians(2.0), A::radians(3.0)]; let sum = A::radians(6.0);
assert_eq!(angles.iter().sum::<A>(), sum);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.