use super::*;
new_unit!(
AngleOf
);
pub type Angle = AngleOf<float>;
pub trait ToAngle<T>: ToAngleComposite<Output = AngleOf<T>>
where
T: CastIntoFloat,
{
}
impl<S, T> ToAngle<T> for S
where
S: ToAngleComposite<Output = AngleOf<T>>,
T: CastIntoFloat,
{
}
pub trait ToAngleComposite
{
type Output;
fn degree(self) -> Self::Output;
fn radian(self) -> Self::Output;
fn turn(self) -> Self::Output;
}
map_on_number!(
($name:ident) =>
{
impl ToAngleComposite for $name
{
type Output = Angle;
fn degree(self) -> Angle { Angle::from_degree(self.to_float()) }
fn radian(self) -> Angle { Angle::from_radian(self.to_float()) }
fn turn (self) -> Angle { Angle::from_turn (self.to_float()) }
}
}
);
impl<T> ToAngleComposite for T
where
T: Map,
T::Item: ToAngleComposite,
{
type Output = T::WithType<<T::Item as ToAngleComposite>::Output>;
fn degree(self) -> Self::Output { self.map(ToAngleComposite::degree) }
fn radian(self) -> Self::Output { self.map(ToAngleComposite::radian) }
fn turn(self) -> Self::Output { self.map(ToAngleComposite::turn) }
}
#[cfg(feature = "serde")]
impl<T> Serialize for AngleOf<T>
where
T: Float + Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.degree().serialize(serializer)
}
}
#[cfg(feature = "serde")]
impl<'de, T> Deserialize<'de> for AngleOf<T>
where
T: Float + Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
Ok(Self::from_degree(T::deserialize(deserializer)?))
}
}
impl<T: Float> AngleOf<T>
{
pub const FULL: Self = AngleOf(T::TWO_PI);
pub const HALF: Self = AngleOf(T::PI);
pub const FLAT: Self = AngleOf(T::PI);
pub const RIGHT: Self = AngleOf(T::HALF_PI);
pub fn from_radian(rad: T) -> Self { Self(rad) }
pub fn from_degree(degree: T) -> Self
{
Self(degree * (T::ANGLE_FULL_RADIAN / T::ANGLE_FULL_DEGREE))
}
pub fn from_turn(coef: T) -> Self { Self(coef * T::ANGLE_FULL_RADIAN) }
pub fn radian(self) -> T { self.0 }
pub fn degree(self) -> T { self.0 * (T::ANGLE_FULL_DEGREE / T::ANGLE_FULL_RADIAN) }
pub fn turn(self) -> T { self.0 / T::ANGLE_FULL_RADIAN }
pub fn normalized_positive(self) -> Self
{
Self::from_radian(
(self.0 % T::ANGLE_FULL_RADIAN + T::ANGLE_FULL_RADIAN) % T::ANGLE_FULL_RADIAN,
)
}
pub fn normalized(self) -> Self
{
let tmp = self.normalized_positive();
if tmp < Self::HALF
{
tmp
}
else
{
tmp - Self::FULL
}
}
#[inline(always)]
pub fn cos_sin(self) -> (T, T)
{
let (s, c) = self.0.sin_cos();
(c, s)
}
#[inline(always)]
pub fn sin_cos(self) -> (T, T) { self.0.sin_cos() }
#[inline(always)]
pub fn cos_cos(self) -> (T, T)
{
let c = self.cos();
(c, c)
}
#[inline(always)]
pub fn sin_sin(self) -> (T, T)
{
let s = self.sin();
(s, s)
}
#[inline(always)]
pub fn cos(self) -> T { self.0.cos() }
#[inline(always)]
pub fn cosh(self) -> T { self.0.cosh() }
#[inline(always)]
pub fn sin(self) -> T { self.0.sin() }
#[inline(always)]
pub fn sinh(self) -> T { self.0.sinh() }
#[inline(always)]
pub fn cot(self) -> T { self.0.cot() }
#[inline(always)]
pub fn tan(self) -> T { self.0.tan() }
#[inline(always)]
pub fn tanh(self) -> T { self.0.tanh() }
#[inline(always)]
pub fn to_vec2_normalized(self) -> Vec2
where
T: Into<float>,
{
unsafe { Angle::from_inner_value(self.0.into()).to_vector2_normalized() }
}
#[inline(always)]
pub fn to_vec2(self, length: T) -> Vec2
where
T: Into<float>,
{
unsafe { Angle::from_inner_value(self.0.into()).to_vector2(length.into()) }
}
#[inline(always)]
pub fn to_vector2_normalized(self) -> Vector2<T> { self.to_vector2(T::ONE) }
#[inline(always)]
pub fn to_vector2(self, length: T) -> Vector2<T>
{
Vector2::new(self.cos() * length, self.sin() * length)
}
pub fn inside_range(self, begin: Self, end: Self) -> bool
{
let self_normalized = self.normalized_positive();
let begin_normalized = begin.normalized_positive();
let end_normalized = end.normalized_positive();
if begin_normalized.0 <= end_normalized.0
{
self_normalized.0 >= begin_normalized.0 && self_normalized.0 <= end_normalized.0
}
else
{
self_normalized.0 >= begin_normalized.0 || self_normalized.0 <= end_normalized.0
}
}
}
impl<T: Float> Debug for AngleOf<T>
where
T: Debug,
{
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { write!(f, "{:?}°", self.degree()) }
}
impl<T: Float> Display for AngleOf<T>
where
T: Display,
{
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { write!(f, "{:}°", self.degree()) }
}
impl<T: Float> RangeDefault for AngleOf<T>
{
const RANGE_MIN: Self = Self::ZERO;
const RANGE_HALF: Self = Self::FLAT;
const RANGE_MAX: Self = Self::FULL;
const RANGE: Self = Self::FULL;
}