Skip to main content

space_units/quantities/
orbital.rs

1use super::DisplayWithUnit;
2
3// -------------------------
4// Gravitational parameter (mu = GM)
5// -------------------------
6
7/// A gravitational parameter (mu = GM), stored canonically in m³/s².
8///
9/// # Construction
10/// ```
11/// use space_units::GravitationalParameter;
12/// let mu = GravitationalParameter::from_km3ps2(398_600.4418); // Earth
13/// ```
14///
15/// # Typed arithmetic
16/// - [`GravitationalParameter`] / [`Length`](crate::Length) → [`SpecificEnergy`](crate::SpecificEnergy)
17/// - [`GravitationalParameter`] / [`Area`](crate::Area) → [`Acceleration`](crate::Acceleration)
18#[must_use]
19#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default)]
20pub struct GravitationalParameter(pub(crate) f64);
21
22/// Display/conversion units for [`GravitationalParameter`].
23#[derive(Debug, Clone, Copy, PartialEq, Eq)]
24pub enum GravitationalParameterUnit {
25    /// Cubic meters per second squared (m³/s²) -- SI derived unit.
26    M3PerS2,
27    /// Cubic kilometers per second squared (km³/s²) -- common in astrodynamics.
28    Km3PerS2,
29}
30
31impl GravitationalParameterUnit {
32    const fn symbol(self) -> &'static str {
33        match self {
34            Self::M3PerS2 => "m^3/s^2",
35            Self::Km3PerS2 => "km^3/s^2",
36        }
37    }
38
39    const fn m3ps2_per_unit(self) -> f64 {
40        match self {
41            Self::M3PerS2 => 1.0,
42            Self::Km3PerS2 => 1e9,
43        }
44    }
45}
46
47impl GravitationalParameter {
48    /// Create from m³/s².
49    pub const fn from_m3ps2(val: f64) -> Self {
50        Self(val)
51    }
52
53    /// Create from km³/s².
54    pub const fn from_km3ps2(val: f64) -> Self {
55        Self(val * 1e9)
56    }
57
58    /// Get value in m³/s².
59    pub const fn in_m3ps2(self) -> f64 {
60        self.0
61    }
62
63    /// Get value in km³/s².
64    pub const fn in_km3ps2(self) -> f64 {
65        self.0 / 1e9
66    }
67
68    /// Get value in the specified [`GravitationalParameterUnit`].
69    pub fn in_unit(self, unit: GravitationalParameterUnit) -> f64 {
70        self.0 / unit.m3ps2_per_unit()
71    }
72
73    /// Return a display wrapper that formats this gravitational parameter in the given unit.
74    pub fn display_as(self, unit: GravitationalParameterUnit) -> DisplayWithUnit {
75        DisplayWithUnit {
76            value: self.in_unit(unit),
77            symbol: unit.symbol(),
78        }
79    }
80
81    /// Return the absolute value of this gravitational parameter.
82    pub fn abs(self) -> Self {
83        Self(self.0.abs())
84    }
85}
86
87impl_quantity_display!(GravitationalParameter, "m³/s²");
88
89impl_common_ops!(GravitationalParameter);
90
91// -------------------------
92// Specific angular momentum
93// -------------------------
94
95/// A specific angular momentum quantity, stored canonically in m²/s.
96///
97/// # Construction
98/// ```
99/// use space_units::SpecificAngularMomentum;
100/// let h = SpecificAngularMomentum::from_km2ps(52.0);
101/// ```
102///
103/// # Typed arithmetic
104/// - [`Length`](crate::Length) × [`Velocity`](crate::Velocity) → [`SpecificAngularMomentum`]
105#[must_use]
106#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default)]
107pub struct SpecificAngularMomentum(pub(crate) f64);
108
109/// Display/conversion units for [`SpecificAngularMomentum`].
110#[derive(Debug, Clone, Copy, PartialEq, Eq)]
111pub enum SpecificAngularMomentumUnit {
112    /// Square meters per second (m²/s) -- SI derived unit.
113    M2PerS,
114    /// Square kilometers per second (km²/s) -- common in astrodynamics.
115    Km2PerS,
116}
117
118impl SpecificAngularMomentumUnit {
119    const fn symbol(self) -> &'static str {
120        match self {
121            Self::M2PerS => "m^2/s",
122            Self::Km2PerS => "km^2/s",
123        }
124    }
125
126    const fn m2ps_per_unit(self) -> f64 {
127        match self {
128            Self::M2PerS => 1.0,
129            Self::Km2PerS => 1e6,
130        }
131    }
132}
133
134impl SpecificAngularMomentum {
135    /// Create from m²/s.
136    pub const fn from_m2ps(val: f64) -> Self {
137        Self(val)
138    }
139
140    /// Create from km²/s.
141    pub const fn from_km2ps(val: f64) -> Self {
142        Self(val * 1e6)
143    }
144
145    /// Get value in m²/s.
146    pub const fn in_m2ps(self) -> f64 {
147        self.0
148    }
149
150    /// Get value in km²/s.
151    pub const fn in_km2ps(self) -> f64 {
152        self.0 / 1e6
153    }
154
155    /// Get value in the specified [`SpecificAngularMomentumUnit`].
156    pub fn in_unit(self, unit: SpecificAngularMomentumUnit) -> f64 {
157        self.0 / unit.m2ps_per_unit()
158    }
159
160    /// Return a display wrapper that formats this specific angular momentum in the given unit.
161    pub fn display_as(self, unit: SpecificAngularMomentumUnit) -> DisplayWithUnit {
162        DisplayWithUnit {
163            value: self.in_unit(unit),
164            symbol: unit.symbol(),
165        }
166    }
167
168    /// Return the absolute value of this specific angular momentum.
169    pub fn abs(self) -> Self {
170        Self(self.0.abs())
171    }
172}
173
174impl_quantity_display!(SpecificAngularMomentum, "m²/s");
175
176impl_common_ops!(SpecificAngularMomentum);