use crate::{
DynamicUnits, LengthUnit, Real, TimeUnit, Velocity, impl_value_type_conversions,
supports_absdiffeq, supports_cancellation, supports_quantity_ops, supports_scalar_ops,
supports_shift_ops, supports_value_type_conversion,
};
use std::{fmt, fmt::Debug, marker::PhantomData};
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
pub struct VelocitySquared<UnitLength: LengthUnit, UnitTime: TimeUnit> {
v: Real,
#[cfg_attr(feature = "serde", serde(skip))]
#[cfg_attr(feature = "bevy_reflect", reflect(ignore))]
phantom_1: PhantomData<UnitLength>,
#[cfg_attr(feature = "serde", serde(skip))]
#[cfg_attr(feature = "bevy_reflect", reflect(ignore))]
phantom_2: PhantomData<UnitTime>,
}
supports_quantity_ops!(VelocitySquared<A, B>, LengthUnit, TimeUnit);
supports_shift_ops!(VelocitySquared<A1, B1>, VelocitySquared<A2, B2>, LengthUnit, TimeUnit);
supports_scalar_ops!(VelocitySquared<A, B>, LengthUnit, TimeUnit);
supports_cancellation!(VelocitySquared<A1, B1>, VelocitySquared<A2, B2>, LengthUnit, TimeUnit);
supports_absdiffeq!(VelocitySquared<A, B>, LengthUnit, TimeUnit);
supports_value_type_conversion!(VelocitySquared<A, B>, LengthUnit, TimeUnit, impl_value_type_conversions);
impl<L, T> fmt::Display for VelocitySquared<L, T>
where
L: LengthUnit,
T: TimeUnit,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.v.0, f)?;
write!(f, "{}^2/{}^2", L::UNIT_SHORT_NAME, T::UNIT_SHORT_NAME)
}
}
impl<L, T> VelocitySquared<L, T>
where
L: LengthUnit,
T: TimeUnit,
{
pub fn sqrt(&self) -> Velocity<L, T> {
Velocity::<L, T>::from(self.v.sqrt())
}
pub fn as_dyn(&self) -> DynamicUnits {
DynamicUnits::new2o2::<L, L, T, T>(self.v)
}
}
impl<'a, LA, TA, LB, TB> From<&'a VelocitySquared<LA, TA>> for VelocitySquared<LB, TB>
where
LA: LengthUnit,
TA: TimeUnit,
LB: LengthUnit,
TB: TimeUnit,
{
fn from(v: &'a VelocitySquared<LA, TA>) -> Self {
let length_ratio = Real(LA::METERS_IN_UNIT / LB::METERS_IN_UNIT);
let time_ratio = Real(TB::SECONDS_IN_UNIT / TA::SECONDS_IN_UNIT);
Self {
v: v.v * length_ratio * length_ratio * time_ratio * time_ratio,
phantom_1: PhantomData,
phantom_2: PhantomData,
}
}
}
#[cfg(test)]
mod test {
use crate::meters_per_second;
use approx::assert_abs_diff_eq;
#[test]
fn test_velocity_squared() {
let a = meters_per_second!(1f64);
let b = meters_per_second!(1f64);
assert_abs_diff_eq!(
(a * a + b * b).sqrt(),
meters_per_second!(1.414),
epsilon = 0.001
);
}
}