use super::{AuPerDay, Ephemeris, PlanetState};
use crate::bodies::solar_system::{
Earth, Jupiter, Mars, Mercury, Moon, Neptune, Saturn, Sun, Uranus, Venus,
};
use crate::coordinates::{
cartesian::{Position, Velocity},
centers::{Barycentric, Geocentric, Heliocentric},
frames::EclipticMeanJ2000,
};
use crate::qtty::{AstronomicalUnit, Kilometer};
use crate::time::JulianDate;
#[derive(Debug, Clone, Copy, Default)]
pub struct Vsop87Ephemeris;
impl Ephemeris for Vsop87Ephemeris {
fn try_planet_barycentric(
planet: super::MajorPlanet,
jd: JulianDate,
) -> Result<
Position<Barycentric, EclipticMeanJ2000, AstronomicalUnit>,
super::PlanetEphemerisError,
> {
use super::MajorPlanet::*;
Ok(match planet {
Mercury => crate::bodies::solar_system::Mercury::vsop87e(jd),
Venus => crate::bodies::solar_system::Venus::vsop87e(jd),
Mars => crate::bodies::solar_system::Mars::vsop87e(jd),
Jupiter => crate::bodies::solar_system::Jupiter::vsop87e(jd),
Saturn => crate::bodies::solar_system::Saturn::vsop87e(jd),
Uranus => crate::bodies::solar_system::Uranus::vsop87e(jd),
Neptune => crate::bodies::solar_system::Neptune::vsop87e(jd),
})
}
fn try_pluto_barycentric(
jd: JulianDate,
) -> Result<
Position<Barycentric, EclipticMeanJ2000, AstronomicalUnit>,
super::PlanetEphemerisError,
> {
let helio = crate::bodies::solar_system::PLUTO.orbit.kepler_position(jd);
let sun = <Self as Ephemeris>::try_sun_barycentric(jd)?;
Ok(Position::new(
helio.x() + sun.x(),
helio.y() + sun.y(),
helio.z() + sun.z(),
))
}
#[inline]
fn sun_barycentric(
jd: JulianDate,
) -> Position<Barycentric, EclipticMeanJ2000, AstronomicalUnit> {
Sun::vsop87e(jd)
}
#[inline]
fn earth_barycentric(
jd: JulianDate,
) -> Position<Barycentric, EclipticMeanJ2000, AstronomicalUnit> {
Earth::vsop87e(jd)
}
#[inline]
fn earth_heliocentric(
jd: JulianDate,
) -> Position<Heliocentric, EclipticMeanJ2000, AstronomicalUnit> {
Earth::vsop87a(jd)
}
#[inline]
fn earth_barycentric_velocity(jd: JulianDate) -> Velocity<EclipticMeanJ2000, AuPerDay> {
Earth::vsop87e_vel(jd)
}
#[inline]
fn moon_geocentric(jd: JulianDate) -> Position<Geocentric, EclipticMeanJ2000, Kilometer> {
Moon::get_geo_position(jd)
}
}
macro_rules! impl_vsop87_planet_state {
($($body:ident),+ $(,)?) => {
$(
impl PlanetState<$body> for Vsop87Ephemeris {
#[inline]
fn heliocentric(
jd: JulianDate,
) -> Position<Heliocentric, EclipticMeanJ2000, AstronomicalUnit> {
$body::vsop87a(jd)
}
}
)+
};
}
impl_vsop87_planet_state!(Mercury, Venus, Mars, Jupiter, Saturn, Uranus, Neptune);