use std::ops::{Add, Sub, Mul, Div, Neg};
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub struct Rad(pub f32);
impl Rad {
#[inline(always)]
pub const fn new(radians: f32) -> Self {
Self(radians)
}
#[inline(always)]
pub fn to_deg(self) -> Deg {
Deg(self.0 * 180.0 / std::f32::consts::PI)
}
#[inline(always)]
pub fn as_rad(self) -> f32 {
self.0
}
#[inline]
pub fn normalize(self) -> Self {
let two_pi = std::f32::consts::TAU;
let mut angle = self.0 % two_pi;
if angle < 0.0 {
angle += two_pi;
}
Self(angle)
}
}
impl From<Deg> for Rad {
#[inline(always)]
fn from(deg: Deg) -> Self {
deg.to_rad()
}
}
impl From<f32> for Rad {
#[inline(always)]
fn from(rad: f32) -> Self {
Self(rad)
}
}
impl Add for Rad {
type Output = Self;
#[inline]
fn add(self, other: Self) -> Self {
Self(self.0 + other.0)
}
}
impl Sub for Rad {
type Output = Self;
#[inline]
fn sub(self, other: Self) -> Self {
Self(self.0 - other.0)
}
}
impl Mul<f32> for Rad {
type Output = Self;
#[inline]
fn mul(self, scalar: f32) -> Self {
Self(self.0 * scalar)
}
}
impl Div<f32> for Rad {
type Output = Self;
#[inline]
fn div(self, scalar: f32) -> Self {
Self(self.0 / scalar)
}
}
impl Neg for Rad {
type Output = Self;
#[inline]
fn neg(self) -> Self {
Self(-self.0)
}
}
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub struct Deg(pub f32);
impl Deg {
#[inline(always)]
pub const fn new(degrees: f32) -> Self {
Self(degrees)
}
#[inline(always)]
pub fn to_rad(self) -> Rad {
Rad(self.0 * std::f32::consts::PI / 180.0)
}
#[inline(always)]
pub fn as_deg(self) -> f32 {
self.0
}
#[inline]
pub fn normalize(self) -> Self {
let mut angle = self.0 % 360.0;
if angle < 0.0 {
angle += 360.0;
}
Self(angle)
}
}
impl From<Rad> for Deg {
#[inline(always)]
fn from(rad: Rad) -> Self {
rad.to_deg()
}
}
impl From<f32> for Deg {
#[inline(always)]
fn from(deg: f32) -> Self {
Self(deg)
}
}
impl Add for Deg {
type Output = Self;
#[inline]
fn add(self, other: Self) -> Self {
Self(self.0 + other.0)
}
}
impl Sub for Deg {
type Output = Self;
#[inline]
fn sub(self, other: Self) -> Self {
Self(self.0 - other.0)
}
}
impl Mul<f32> for Deg {
type Output = Self;
#[inline]
fn mul(self, scalar: f32) -> Self {
Self(self.0 * scalar)
}
}
impl Div<f32> for Deg {
type Output = Self;
#[inline]
fn div(self, scalar: f32) -> Self {
Self(self.0 / scalar)
}
}
impl Neg for Deg {
type Output = Self;
#[inline]
fn neg(self) -> Self {
Self(-self.0)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[allow(clippy::upper_case_acronyms)]
pub enum EulerRot {
XYZ,
XZY,
YXZ,
YZX,
ZXY,
ZYX,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_rad_deg_conversion() {
let rad = Rad::new(std::f32::consts::PI);
let deg = rad.to_deg();
assert!((deg.as_deg() - 180.0).abs() < 0.0001);
}
#[test]
fn test_deg_rad_conversion() {
let deg = Deg::new(90.0);
let rad = deg.to_rad();
assert!((rad.as_rad() - std::f32::consts::FRAC_PI_2).abs() < 0.0001);
}
}