use siderust::bodies::solar_system::Mars;
use siderust::coordinates::centers::*;
use siderust::coordinates::frames::*;
use siderust::coordinates::transform::TransformFrame;
use siderust::coordinates::*;
use siderust::qtty::*;
use siderust::time::JulianDate;
fn approx_eq_pos<C, F, U>(a: &cartesian::Position<C, F, U>, b: &cartesian::Position<C, F, U>)
where
C: ReferenceCenter,
F: ReferenceFrame,
U: LengthUnit,
Quantity<U>: std::cmp::PartialOrd,
{
assert!(
(a.x() - b.x()).abs() < (1e-6).into(),
"x mismatch: {} vs {}",
a.x().value(),
b.x().value()
);
assert!(
(a.y() - b.y()).abs() < (1e-6).into(),
"y mismatch: {} vs {}",
a.y().value(),
b.y().value()
);
assert!(
(a.z() - b.z()).abs() < (1e-6).into(),
"z mismatch: {} vs {}",
a.z().value(),
b.z().value()
);
}
fn approx_eq_dir<F>(a: &cartesian::Direction<F>, b: &cartesian::Direction<F>)
where
F: ReferenceFrame,
{
assert!(
(a.x() - b.x()).abs() < 1e-6,
"x mismatch: {} vs {}",
a.x(),
b.x()
);
assert!(
(a.y() - b.y()).abs() < 1e-6,
"y mismatch: {} vs {}",
a.y(),
b.y()
);
assert!(
(a.z() - b.z()).abs() < 1e-6,
"z mismatch: {} vs {}",
a.z(),
b.z()
);
}
fn sph_approx_eq<C, F, U>(a: &spherical::Position<C, F, U>, b: &spherical::Position<C, F, U>)
where
C: ReferenceCenter,
F: ReferenceFrame,
U: LengthUnit,
Quantity<U>: std::cmp::PartialOrd + std::fmt::Display,
{
assert!(
(a.polar - b.polar).abs().value() < 1e-6,
"polar mismatch: {} vs {}",
a.polar,
b.polar
);
assert!(
(a.azimuth - b.azimuth).abs().value() < 1e-6,
"polar mismatch: {} vs {}",
a.azimuth,
b.azimuth
);
assert!(
(a.distance - b.distance).abs() < (1e-6).into(),
"polar mismatch: {} vs {}",
a.distance,
b.distance
);
}
#[test]
fn test_position_transformations() {
use siderust::coordinates::transform::Transform;
let original = Mars::vsop87a(JulianDate::J2000);
let helio_eq: cartesian::Position<Heliocentric, EquatorialMeanJ2000, _> =
original.transform(JulianDate::J2000);
let helio_from_eq: cartesian::Position<Heliocentric, EclipticMeanJ2000, _> =
helio_eq.transform(JulianDate::J2000);
approx_eq_pos(&original, &helio_from_eq);
}
#[test]
fn test_direction_frame_transformations() {
use siderust::coordinates::cartesian::Direction;
let original: Direction<EclipticMeanJ2000> = Mars::vsop87a(JulianDate::J2000)
.direction()
.expect("Mars position should have a direction");
let equatorial: Direction<EquatorialMeanJ2000> = TransformFrame::to_frame(&original);
let ecliptic_back: Direction<EclipticMeanJ2000> = TransformFrame::to_frame(&equatorial);
approx_eq_dir(&original, &ecliptic_back);
let norm = (equatorial.x().powi(2) + equatorial.y().powi(2) + equatorial.z().powi(2)).sqrt();
assert!(
(norm - 1.0).abs() < 1e-12,
"direction should be unit vector"
);
}
#[test]
fn test_spherical_direction_transformations() {
let cart_original: cartesian::Direction<EclipticMeanJ2000> = Mars::vsop87a(JulianDate::J2000)
.direction()
.expect("Mars position should have a direction");
let sph = cart_original.to_spherical();
let back = sph.to_cartesian();
approx_eq_dir(&cart_original, &back);
}
#[test]
fn serialize_cartesian_spherical() {
let sph_orig = spherical::Position::<Barycentric, ICRS, AstronomicalUnit>::new(
Degrees::new(101.28715533),
Degrees::new(-16.71611586),
1.0,
);
let cart = sph_orig.to_cartesian();
let sph_rec = spherical::Position::from_cartesian(&cart);
sph_approx_eq(&sph_orig, &sph_rec);
}
#[test]
fn test_line_of_sight() {
use siderust::coordinates::cartesian::line_of_sight;
let observer = cartesian::Position::<Heliocentric, EclipticMeanJ2000, AstronomicalUnit>::new(
AstronomicalUnits::new(1.0),
AstronomicalUnits::new(0.0),
AstronomicalUnits::new(0.0),
);
let target = cartesian::Position::<Heliocentric, EclipticMeanJ2000, AstronomicalUnit>::new(
AstronomicalUnits::new(2.0),
AstronomicalUnits::new(0.0),
AstronomicalUnits::new(0.0),
);
let los = line_of_sight(&observer, &target);
assert!((los.x() - 1.0).abs() < 1e-12);
assert!(los.y().abs() < 1e-12);
assert!(los.z().abs() < 1e-12);
}