use crate::coordinates::spherical::direction;
use crate::time::JulianDate;
use super::CoordinateWithPM;
pub trait Trackable {
type Coords;
fn track(&self, jd: JulianDate) -> Self::Coords;
}
impl Trackable for direction::ICRS {
type Coords = direction::ICRS;
#[inline]
fn track(&self, _jd: JulianDate) -> Self::Coords {
*self
}
}
impl<T: Clone> Trackable for CoordinateWithPM<T> {
type Coords = T;
#[inline]
fn track(&self, _jd: JulianDate) -> Self::Coords {
self.position.clone()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::time::JulianDate;
#[test]
fn icrs_direction_is_time_invariant() {
let dir = direction::ICRS::new(
crate::qtty::Degrees::new(101.287),
crate::qtty::Degrees::new(-16.716),
);
let at_j2000 = dir.track(crate::J2000);
let at_j2050 = dir.track(crate::time::JulianDate::new(
(crate::J2000.raw() + crate::qtty::Days::new(365.25 * 50.0)).value(),
));
assert_eq!(at_j2000.ra(), at_j2050.ra());
assert_eq!(at_j2000.dec(), at_j2050.dec());
}
#[test]
fn coordinate_with_pm_returns_stored_position() {
use crate::coordinates::spherical::position;
let pos = position::EquatorialMeanJ2000::<crate::qtty::LightYear>::new(
crate::qtty::Degrees::new(88.0),
crate::qtty::Degrees::new(7.0),
crate::qtty::LightYears::new(548.0),
);
let sample = CoordinateWithPM::new_static(pos, crate::J2000);
let result = sample.track(crate::time::JulianDate::new(
(crate::J2000.raw() + crate::qtty::Days::new(365.25)).value(),
));
assert_eq!(result.ra(), crate::qtty::Degrees::new(88.0));
assert_eq!(result.dec(), crate::qtty::Degrees::new(7.0));
}
#[test]
fn generic_trackable_function() {
fn track_anything<T: Trackable>(obj: &T, jd: JulianDate) -> T::Coords {
obj.track(jd)
}
let dir = direction::ICRS::new(
crate::qtty::Degrees::new(45.0),
crate::qtty::Degrees::new(30.0),
);
let result = track_anything(&dir, crate::J2000);
assert_eq!(result.ra(), crate::qtty::Degrees::new(45.0));
assert_eq!(result.dec(), crate::qtty::Degrees::new(30.0));
}
}