astro_rs/coordinates/
mod.rs

1//! Compare, calculate, and transform spacial coordinates
2
3mod frames;
4mod lookup;
5mod lookup_config;
6
7use rust_decimal::Decimal;
8use uom::si::angle::radian;
9use uom::si::f64::{Angle, Length};
10use uom::ConstZero;
11
12pub use frames::*;
13pub use lookup::*;
14pub use lookup_config::*;
15
16/// Equitorial coordinates expressed as (right ascension, declination)
17#[derive(Debug, Default, Copy, Clone, PartialEq)]
18pub struct EquatorialCoord {
19    /// The right ascension angle
20    pub ra: Angle,
21    /// The declination angle
22    pub dec: Angle,
23}
24
25impl EquatorialCoord {
26    /// Constructs an EquitorialCoord. The given right ascension and declination angles will be normalized to [0.0, 2π)
27    pub fn new(ra: Angle, dec: Angle) -> Self {
28        Self {
29            ra: Self::normalize(ra),
30            dec: Self::normalize(dec),
31        }
32    }
33
34    fn normalize(a: Angle) -> Angle {
35        if a < Angle::ZERO {
36            (a % Angle::FULL_TURN) + Angle::FULL_TURN
37        } else {
38            a % Angle::FULL_TURN
39        }
40    }
41
42    /// Creates a new EquitorialCoord with the angle values rounded to the specified decimal place.
43    pub fn round(&self, dp: u32) -> Self {
44        let ra = Decimal::from_f64_retain(self.ra.value)
45            .unwrap()
46            .round_dp(dp)
47            .try_into()
48            .unwrap();
49        let dec = Decimal::from_f64_retain(self.dec.value)
50            .unwrap()
51            .round_dp(dp)
52            .try_into()
53            .unwrap();
54        Self {
55            ra: Angle::new::<radian>(ra),
56            dec: Angle::new::<radian>(dec),
57        }
58    }
59}
60
61/// Coordinates that represent a location on Earth.
62#[derive(Debug, Default, Copy, Clone, PartialEq)]
63pub struct EarthLocation {
64    /// The latitude coordinate
65    pub lat: Angle,
66    /// The longitude coordinate
67    pub lon: Angle,
68    /// The height of the location
69    pub height: Length,
70}