use prelude::*;
use super::Vec2;
#[cfg_attr(feature = "serialize-serde", derive(Deserialize, Serialize))]
#[derive(Copy, Clone, PartialEq, PartialOrd)]
pub struct Angle<T = f32>(pub T);
impl<T> Angle<T> where T: Float {
pub fn to_radians(self: &Self) -> T {
self.0
}
pub fn to_degrees(self: &Self) -> T {
self.0.to_degrees()
}
#[deprecated(since = "0.2.2", note = "use Vec2::from() instead")]
pub fn to_vec2(self: &Self) -> Vec2<T> {
Vec2::from(*self)
}
pub fn from_radians(radians: T) -> Self {
Angle::<T>(radians)
}
pub fn from_degrees(degrees: T) -> Self {
Self::from_radians(degrees.to_radians())
}
#[allow(non_snake_case)]
pub fn normalize(self: &Self) -> Self {
let PI = NumCast::from(f64::consts::PI).unwrap();
if self.0.abs() > PI {
let two_PI = NumCast::from(f64::consts::PI * 2.0).unwrap();
Angle(self.0 - two_PI * ((self.0 + PI) / two_PI).floor())
} else {
*self
}
}
pub fn diff(self: &Self, other: Self) -> Self {
let mut this = *self;
this.align_with(other);
this - other
}
#[allow(non_snake_case)]
pub fn align_with(self: &mut Self, target: Self) -> &mut Self {
let PI = NumCast::from(f64::consts::PI).unwrap();
let two_PI = NumCast::from(f64::consts::PI * 2.0).unwrap();
if self.0.abs() > PI {
self.0 = self.0 - two_PI * ((self.0 + PI) / two_PI).floor();
}
let target_radians = if target.0.abs() > PI {
target.0 - two_PI * ((target.0 + PI) / two_PI).floor()
} else {
target.0
};
let diff = self.0 - target_radians;
if diff.abs() > PI {
self.0 = self.0 - diff.signum() * two_PI;
}
self
}
}
impl<T> From<Vec2<T>> for Angle<T> where T: Float {
fn from(vec: Vec2<T>) -> Angle<T> {
Angle(vec.1.atan2(vec.0))
}
}
impl<T> From<T> for Angle<T> where T: Float {
fn from(other: T) -> Angle<T> {
Angle(other)
}
}
impl From<Angle<f64>> for f64 {
fn from(other: Angle<f64>) -> f64 {
other.to_radians() as f64
}
}
impl From<Angle<f32>> for f32 {
fn from(other: Angle<f32>) -> f32 {
other.to_radians() as f32
}
}
impl<'a> From<&'a Angle<f64>> for f64 {
fn from(other: &'a Angle<f64>) -> f64 {
other.to_radians() as f64
}
}
impl<'a> From<&'a Angle<f32>> for f32 {
fn from(other: &'a Angle<f32>) -> f32 {
other.to_radians() as f32
}
}
impl<T> Default for Angle<T> where T: Float {
fn default() -> Self {
Angle(T::zero())
}
}
impl<T> ToPrimitive for Angle<T> where T: Float {
fn to_f64(self: &Self) -> Option<f64> {
NumCast::from(self.to_radians())
}
fn to_f32(self: &Self) -> Option<f32> {
NumCast::from(self.to_radians())
}
fn to_i64(self: &Self) -> Option<i64> {
NumCast::from(self.to_radians())
}
fn to_u64(self: &Self) -> Option<u64> {
let value = self.to_radians();
if value >= T::zero() { NumCast::from(self.to_radians()) } else { None }
}
}
impl<T> FromPrimitive for Angle<T> where T: Float {
fn from_f64(n: f64) -> Option<Angle<T>> {
Some(Angle(NumCast::from(n).unwrap()))
}
fn from_f32(n: f32) -> Option<Angle<T>> {
Some(Angle(NumCast::from(n).unwrap()))
}
fn from_i64(n: i64) -> Option<Angle<T>> {
Some(Angle(NumCast::from(n).unwrap()))
}
fn from_u64(n: u64) -> Option<Angle<T>> {
Some(Angle(NumCast::from(n).unwrap()))
}
}
impl<T> Neg for Angle<T> where T: Float {
type Output = Angle<T>;
fn neg(self) -> Angle<T> {
Angle::<T>(-self.0)
}
}
impl<T> Add for Angle<T> where T: Float {
type Output = Angle<T>;
fn add(self, other: Angle<T>) -> Angle<T> {
Angle::<T>(self.0 + other.0)
}
}
impl<T> AddAssign for Angle<T> where T: Float {
fn add_assign(self: &mut Self, other: Angle<T>) {
*self = Angle::<T>(self.0 + other.0)
}
}
impl<T> Sub for Angle<T> where T: Float {
type Output = Angle<T>;
fn sub(self, other: Angle<T>) -> Angle<T> {
Angle::<T>(self.0 - other.0)
}
}
impl<T> SubAssign for Angle<T> where T: Float {
fn sub_assign(self: &mut Self, other: Angle<T>) {
*self = Angle::<T>(self.0 - other.0)
}
}
impl<T> Mul<Angle<T>> for Angle<T> where T: Float {
type Output = Angle<T>;
fn mul(self, other: Angle<T>) -> Angle<T> {
Angle::<T>(self.0 * other.0)
}
}
impl<T> MulAssign for Angle<T> where T: Float {
fn mul_assign(&mut self, other: Angle<T>) {
*self = Angle::<T>(self.0 * other.0)
}
}
impl<T> Mul<T> for Angle<T> where T: Float {
type Output = Angle<T>;
fn mul(self, other: T) -> Angle<T> {
Angle::<T>(self.0 * other)
}
}
impl<T> Div<Angle<T>> for Angle<T> where T: Float {
type Output = Angle<T>;
fn div(self, other: Angle<T>) -> Angle<T> {
Angle::<T>(self.0 / other.0)
}
}
impl<T> DivAssign for Angle<T> where T: Float {
fn div_assign(&mut self, other: Angle<T>) {
*self = Angle::<T>(self.0 / other.0)
}
}
impl<T> Div<T> for Angle<T> where T: Float {
type Output = Angle<T>;
fn div(self, other: T) -> Angle<T> {
Angle::<T>(self.0 / other)
}
}
#[cfg(feature = "uniforms")]
use radiant_rs::{Uniform, AsUniform};
#[cfg(feature = "uniforms")]
impl AsUniform for Angle<f32> {
fn as_uniform(&self) -> Uniform {
Uniform::Float(self.0)
}
}
#[cfg(feature = "uniforms")]
impl AsUniform for Angle<f64> {
fn as_uniform(&self) -> Uniform {
Uniform::Double(self.0)
}
}
impl<T> Debug for Angle<T> where T: Debug + Float {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Angle({:?})", self.0)
}
}