Skip to content

Commit

Permalink
refactor: prefer Result over Option for Origin props
Browse files Browse the repository at this point in the history
  • Loading branch information
helgee committed Dec 19, 2024
1 parent 67a4555 commit 0cd59d0
Show file tree
Hide file tree
Showing 12 changed files with 486 additions and 389 deletions.
544 changes: 278 additions & 266 deletions crates/lox-bodies/src/generated.rs

Large diffs are not rendered by default.

107 changes: 53 additions & 54 deletions crates/lox-bodies/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,40 +35,33 @@ pub trait Origin {
fn name(&self) -> &'static str;
}

#[derive(Clone, Debug, Error, Eq, PartialEq)]
#[error("undefined property '{prop}' for origin '{origin}'")]
pub struct UndefinedOriginPropertyError {
origin: String,
prop: String,
}

pub type Radii = (f64, f64, f64);

pub trait MaybeTriaxialEllipsoid: Origin {
fn maybe_radii(&self) -> Option<Radii>;
pub trait TryTriaxialEllipsoid: Origin {
fn try_radii(&self) -> Result<Radii, UndefinedOriginPropertyError>;
}

pub trait TriaxialEllipsoid: Origin {
fn radii(&self) -> Radii;
}

impl<T: TriaxialEllipsoid> MaybeTriaxialEllipsoid for T {
fn maybe_radii(&self) -> Option<Radii> {
Some(self.radii())
impl<T: TriaxialEllipsoid> TryTriaxialEllipsoid for T {
fn try_radii(&self) -> Result<Radii, UndefinedOriginPropertyError> {
Ok(self.radii())
}
}

fn flattening(equatorial_radius: f64, polar_radius: f64) -> f64 {
(equatorial_radius - polar_radius) / equatorial_radius
}

pub trait MaybeSpheroid: MaybeTriaxialEllipsoid {
fn maybe_polar_radius(&self) -> Option<f64> {
self.maybe_radii().map(|radii| radii.0)
}

fn maybe_equatorial_radius(&self) -> Option<f64> {
self.maybe_radii().map(|radii| radii.2)
}

fn maybe_flattening(&self) -> Option<f64> {
self.maybe_radii().map(|radii| flattening(radii.0, radii.2))
}
}

pub trait Spheroid: TriaxialEllipsoid {
fn equatorial_radius(&self) -> f64 {
self.radii().0
Expand All @@ -83,45 +76,59 @@ pub trait Spheroid: TriaxialEllipsoid {
}
}

impl<T: Spheroid> MaybeSpheroid for T {
fn maybe_polar_radius(&self) -> Option<f64> {
Some(self.polar_radius())
pub trait TrySpheroid: TryTriaxialEllipsoid {
fn try_equatorial_radius(&self) -> Result<f64, UndefinedOriginPropertyError> {
self.try_radii().map(|radii| radii.2)
}

fn maybe_equatorial_radius(&self) -> Option<f64> {
Some(self.equatorial_radius())
fn try_polar_radius(&self) -> Result<f64, UndefinedOriginPropertyError> {
self.try_radii().map(|radii| radii.0)
}

fn maybe_flattening(&self) -> Option<f64> {
Some(self.flattening())
fn try_flattening(&self) -> Result<f64, UndefinedOriginPropertyError> {
self.try_radii().map(|radii| flattening(radii.0, radii.2))
}
}

pub trait MaybeMeanRadius: Origin {
fn maybe_mean_radius(&self) -> Option<f64>;
impl<T: Spheroid> TrySpheroid for T {
fn try_equatorial_radius(&self) -> Result<f64, UndefinedOriginPropertyError> {
Ok(self.equatorial_radius())
}

fn try_polar_radius(&self) -> Result<f64, UndefinedOriginPropertyError> {
Ok(self.polar_radius())
}

fn try_flattening(&self) -> Result<f64, UndefinedOriginPropertyError> {
Ok(self.flattening())
}
}

pub trait TryMeanRadius: Origin {
fn try_mean_radius(&self) -> Result<f64, UndefinedOriginPropertyError>;
}

pub trait MeanRadius: Origin {
fn mean_radius(&self) -> f64;
}

impl<T: MeanRadius> MaybeMeanRadius for T {
fn maybe_mean_radius(&self) -> Option<f64> {
Some(self.mean_radius())
impl<T: MeanRadius> TryMeanRadius for T {
fn try_mean_radius(&self) -> Result<f64, UndefinedOriginPropertyError> {
Ok(self.mean_radius())
}
}

pub trait PointMass: Origin {
fn gravitational_parameter(&self) -> f64;
}

pub trait MaybePointMass: Origin {
fn maybe_gravitational_parameter(&self) -> Option<f64>;
pub trait TryPointMass: Origin {
fn try_gravitational_parameter(&self) -> Result<f64, UndefinedOriginPropertyError>;
}

impl<T: PointMass> MaybePointMass for T {
fn maybe_gravitational_parameter(&self) -> Option<f64> {
Some(self.gravitational_parameter())
impl<T: PointMass> TryPointMass for T {
fn try_gravitational_parameter(&self) -> Result<f64, UndefinedOriginPropertyError> {
Ok(self.gravitational_parameter())
}
}

Expand Down Expand Up @@ -273,56 +280,48 @@ pub trait RotationalElements: Origin {
}
}

#[derive(Clone, Debug, Error, Eq, PartialEq)]
#[error("no rotational elements defined for origin `{0}`")]
pub struct UndefinedRotationalElementsError(String);

pub trait TryRotationalElements: Origin {
fn try_rotational_elements(&self, t: f64)
-> Result<Elements, UndefinedRotationalElementsError>;
fn try_rotational_elements(&self, t: f64) -> Result<Elements, UndefinedOriginPropertyError>;

fn try_rotational_element_rates(
&self,
t: f64,
) -> Result<Elements, UndefinedRotationalElementsError>;
) -> Result<Elements, UndefinedOriginPropertyError>;

fn try_right_ascension(&self, t: f64) -> Result<f64, UndefinedRotationalElementsError> {
fn try_right_ascension(&self, t: f64) -> Result<f64, UndefinedOriginPropertyError> {
self.try_rotational_elements(t).map(|r| r.0)
}

fn try_right_ascension_rate(&self, t: f64) -> Result<f64, UndefinedRotationalElementsError> {
fn try_right_ascension_rate(&self, t: f64) -> Result<f64, UndefinedOriginPropertyError> {
self.try_rotational_element_rates(t).map(|r| r.0)
}

fn try_declination(&self, t: f64) -> Result<f64, UndefinedRotationalElementsError> {
fn try_declination(&self, t: f64) -> Result<f64, UndefinedOriginPropertyError> {
self.try_rotational_elements(t).map(|r| r.1)
}

fn try_declination_rate(&self, t: f64) -> Result<f64, UndefinedRotationalElementsError> {
fn try_declination_rate(&self, t: f64) -> Result<f64, UndefinedOriginPropertyError> {
self.try_rotational_element_rates(t).map(|r| r.1)
}

fn try_rotation_angle(&self, t: f64) -> Result<f64, UndefinedRotationalElementsError> {
fn try_rotation_angle(&self, t: f64) -> Result<f64, UndefinedOriginPropertyError> {
self.try_rotational_elements(t).map(|r| r.2)
}

fn try_rotation_rate(&self, t: f64) -> Result<f64, UndefinedRotationalElementsError> {
fn try_rotation_rate(&self, t: f64) -> Result<f64, UndefinedOriginPropertyError> {
self.try_rotational_element_rates(t).map(|r| r.2)
}
}

impl<T: RotationalElements> TryRotationalElements for T {
fn try_rotational_elements(
&self,
t: f64,
) -> Result<Elements, UndefinedRotationalElementsError> {
fn try_rotational_elements(&self, t: f64) -> Result<Elements, UndefinedOriginPropertyError> {
Ok(self.rotational_elements(t))
}

fn try_rotational_element_rates(
&self,
t: f64,
) -> Result<Elements, UndefinedRotationalElementsError> {
) -> Result<Elements, UndefinedOriginPropertyError> {
Ok(self.rotational_element_rates(t))
}
}
Expand Down
71 changes: 68 additions & 3 deletions crates/lox-bodies/src/python.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,25 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
*/
use pyo3::exceptions::{PyTypeError, PyValueError};
use crate::dynamic::{DynOrigin, UnknownOriginId, UnknownOriginName};
use crate::{
Elements, Origin, TryMeanRadius, TryPointMass, TryRotationalElements, TrySpheroid,
TryTriaxialEllipsoid,
};
use crate::{Radii, UndefinedOriginPropertyError as RsUndefinedPropertyError};
use lox_math::types::units::Seconds;
use pyo3::create_exception;
use pyo3::exceptions::{PyException, PyTypeError, PyValueError};
use pyo3::prelude::*;
use std::str::FromStr;

use crate::dynamic::{DynOrigin, UnknownOriginId, UnknownOriginName};
use crate::Origin;
create_exception!(lox_space, UndefinedOriginPropertyError, PyException);

impl From<RsUndefinedPropertyError> for PyErr {
fn from(err: RsUndefinedPropertyError) -> Self {
UndefinedOriginPropertyError::new_err(err.to_string())
}
}

impl From<UnknownOriginId> for PyErr {
fn from(err: UnknownOriginId) -> Self {
Expand Down Expand Up @@ -62,4 +75,56 @@ impl PyOrigin {
pub fn name(&self) -> &'static str {
self.0.name()
}

pub fn gravitational_parameter(&self) -> PyResult<f64> {
Ok(self.0.try_gravitational_parameter()?)
}

pub fn mean_radius(&self) -> PyResult<f64> {
Ok(self.0.try_mean_radius()?)
}

pub fn radii(&self) -> PyResult<Radii> {
Ok(self.0.try_radii()?)
}

pub fn equatorial_radius(&self) -> PyResult<f64> {
Ok(self.0.try_equatorial_radius()?)
}

pub fn polar_radius(&self) -> PyResult<f64> {
Ok(self.0.try_polar_radius()?)
}

pub fn rotational_elements(&self, et: Seconds) -> PyResult<Elements> {
Ok(self.0.try_rotational_elements(et)?)
}

pub fn rotational_element_rates(&self, et: Seconds) -> PyResult<Elements> {
Ok(self.0.try_rotational_element_rates(et)?)
}

pub fn right_ascension(&self, et: Seconds) -> PyResult<f64> {
Ok(self.0.try_right_ascension(et)?)
}

pub fn right_ascension_rate(&self, et: Seconds) -> PyResult<f64> {
Ok(self.0.try_right_ascension_rate(et)?)
}

pub fn declination(&self, et: Seconds) -> PyResult<f64> {
Ok(self.0.try_declination(et)?)
}

pub fn declination_rate(&self, et: Seconds) -> PyResult<f64> {
Ok(self.0.try_declination_rate(et)?)
}

pub fn rotation_angle(&self, et: Seconds) -> PyResult<f64> {
Ok(self.0.try_rotation_angle(et)?)
}

pub fn rotation_rate(&self, et: Seconds) -> PyResult<f64> {
Ok(self.0.try_rotation_rate(et)?)
}
}
4 changes: 2 additions & 2 deletions crates/lox-orbits/src/analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::f64::consts::PI;
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
*/
use lox_bodies::{MaybeSpheroid, Origin, RotationalElements, Spheroid};
use lox_bodies::{Origin, RotationalElements, Spheroid, TrySpheroid};
use lox_math::roots::Brent;
use lox_math::series::{Series, SeriesError};
use lox_math::types::units::Radians;
Expand Down Expand Up @@ -115,7 +115,7 @@ pub fn visibility_dyn<T: TimeLike + TryToScale<Tdb, P> + Clone, P: FrameTransfor

pub fn elevation<
T: TimeLike + TryToScale<Tdb, P> + Clone,
O: Origin + MaybeSpheroid + RotationalElements + Clone,
O: Origin + TrySpheroid + RotationalElements + Clone,
P: FrameTransformationProvider,
>(
time: T,
Expand Down
18 changes: 8 additions & 10 deletions crates/lox-orbits/src/elements.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use std::f64::consts::TAU;
use float_eq::float_eq;
use glam::{DMat3, DVec3};

use lox_bodies::{DynOrigin, MaybePointMass, PointMass};
use lox_bodies::{DynOrigin, PointMass, TryPointMass, UndefinedOriginPropertyError};
use lox_time::deltas::TimeDelta;
use lox_time::TimeLike;

Expand All @@ -29,7 +29,7 @@ pub(crate) struct KeplerianElements {
}

#[derive(Debug, Clone, PartialEq)]
pub struct Keplerian<T: TimeLike, O: MaybePointMass, R: ReferenceFrame> {
pub struct Keplerian<T: TimeLike, O: TryPointMass, R: ReferenceFrame> {
time: T,
origin: O,
frame: R,
Expand Down Expand Up @@ -87,10 +87,8 @@ where
longitude_of_ascending_node: f64,
argument_of_periapsis: f64,
true_anomaly: f64,
) -> Result<Self, &'static str> {
if origin.maybe_gravitational_parameter().is_none() {
return Err("undefined gravitational parameter");
}
) -> Result<Self, UndefinedOriginPropertyError> {
let _ = origin.try_gravitational_parameter()?;
Ok(Self {
time,
origin,
Expand All @@ -108,7 +106,7 @@ where
impl<T, O, R> Keplerian<T, O, R>
where
T: TimeLike,
O: MaybePointMass,
O: TryPointMass,
R: ReferenceFrame,
{
pub fn origin(&self) -> O
Expand All @@ -127,7 +125,7 @@ where

pub fn gravitational_parameter(&self) -> f64 {
self.origin
.maybe_gravitational_parameter()
.try_gravitational_parameter()
.expect("gravitational parameter should be available")
}

Expand Down Expand Up @@ -182,7 +180,7 @@ where
}
}

impl<T: TimeLike, O: MaybePointMass, R: ReferenceFrame + Clone> CoordinateSystem<R>
impl<T: TimeLike, O: TryPointMass, R: ReferenceFrame + Clone> CoordinateSystem<R>
for Keplerian<T, O, R>
{
fn reference_frame(&self) -> R {
Expand All @@ -193,7 +191,7 @@ impl<T: TimeLike, O: MaybePointMass, R: ReferenceFrame + Clone> CoordinateSystem
impl<T, O, R> Keplerian<T, O, R>
where
T: TimeLike + Clone,
O: MaybePointMass + Clone,
O: TryPointMass + Clone,
R: ReferenceFrame + Clone,
{
pub(crate) fn to_cartesian(&self) -> State<T, O, R> {
Expand Down
4 changes: 2 additions & 2 deletions crates/lox-orbits/src/frames/iau.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/
use crate::rotations::Rotation;
use glam::{DMat3, DVec3};
use lox_bodies::{TryRotationalElements, UndefinedRotationalElementsError};
use lox_bodies::{TryRotationalElements, UndefinedOriginPropertyError};
use lox_time::julian_dates::JulianDate;
use lox_time::time_scales::Tdb;
use lox_time::transformations::{OffsetProvider, TryToScale};
Expand All @@ -18,7 +18,7 @@ use thiserror::Error;
#[derive(Clone, Debug, Error)]
pub enum IcrfToBodyFixedError {
#[error(transparent)]
UndefinedRotationalElements(#[from] UndefinedRotationalElementsError),
UndefinedRotationalElements(#[from] UndefinedOriginPropertyError),
#[error("time error: {0}")]
TimeError(String),
}
Expand Down
Loading

0 comments on commit 0cd59d0

Please sign in to comment.