polyhorn_ui/
physics.rs

1//! Primitives for a few physics-based types (velocity, angles).
2
3use num_traits::{Float, FloatConst};
4use std::fmt::{Debug, Formatter, Result};
5use std::ops::{Add, Div, Neg, Sub};
6use std::time::Duration;
7
8/// Represents dy/dt. This type is mostly used for events that involve movement,
9/// such as scroll events.
10pub struct Velocity<T> {
11    delta: T,
12    time: Duration,
13}
14
15impl<T> Velocity<T> {
16    /// Returns a new velocity with the given delta within the given timeframe.
17    pub fn new(delta: T, time: Duration) -> Velocity<T> {
18        Velocity { delta, time }
19    }
20
21    /// Returns the velocity in O per second where O is the result of dividing
22    /// T by a f32 that represents the duration of this velocity sample.
23    pub fn into_per_second<X, O>(self) -> O
24    where
25        X: From<f32>,
26        T: Div<X, Output = O>,
27    {
28        self.delta / X::from(self.time.as_secs_f32())
29    }
30}
31
32/// Type-safe representation for angles.
33#[derive(Copy, Clone, Default, Eq, PartialEq)]
34pub struct Angle<T> {
35    radians: T,
36}
37
38impl<T> Angle<T>
39where
40    T: Float,
41{
42    /// Returns a new angle with the given radians.
43    pub fn with_radians(radians: T) -> Angle<T> {
44        Angle { radians }
45    }
46
47    /// Converts the given angle to radians.
48    pub fn to_radians(&self) -> T {
49        self.radians
50    }
51}
52
53impl<T> Angle<T>
54where
55    T: Float + FloatConst,
56{
57    /// Returns a new angle with the given degrees.
58    pub fn with_degrees(degrees: T) -> Angle<T> {
59        Angle {
60            radians: degrees / T::from(180.0).unwrap() * T::PI(),
61        }
62    }
63
64    /// Converts the given angle to degrees.
65    pub fn to_degrees(&self) -> T {
66        self.radians / T::PI() * T::from(180.0).unwrap()
67    }
68}
69
70impl<T> Add for &Angle<T>
71where
72    T: Float + FloatConst,
73{
74    type Output = Angle<T>;
75
76    fn add(self, rhs: &Angle<T>) -> Self::Output {
77        Angle {
78            radians: self.radians + rhs.radians,
79        }
80    }
81}
82
83impl<T> Sub for &Angle<T>
84where
85    T: Float + FloatConst,
86{
87    type Output = Angle<T>;
88
89    fn sub(self, rhs: &Angle<T>) -> Self::Output {
90        Angle {
91            radians: self.radians - rhs.radians,
92        }
93    }
94}
95
96impl<T> Neg for Angle<T>
97where
98    T: Neg,
99{
100    type Output = Angle<T::Output>;
101
102    fn neg(self) -> Self::Output {
103        Angle {
104            radians: self.radians.neg(),
105        }
106    }
107}
108
109impl<T> Debug for Angle<T>
110where
111    T: Float + FloatConst + Debug,
112{
113    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
114        f.write_fmt(format_args!("{:?}ยบ", self.to_degrees()))
115    }
116}