use skymath::{alt_az, Angle, Equatorial, Location};
use time::macros::datetime;
fn eq(ra: f64, dec: f64) -> Equatorial {
Equatorial::j2000(Angle::from_degrees(ra), Angle::from_degrees(dec)).unwrap()
}
fn site(lat: f64, lon: f64, elev: f64) -> Location {
Location::new(Angle::from_degrees(lat), Angle::from_degrees(lon), elev).unwrap()
}
#[test]
fn vega_from_kitt_peak_matches_astropy() {
let observer = site(31.9583, -111.6, 2120.0);
let vega = eq(279.234_734_79, 38.783_688_96);
let h = alt_az(vega, datetime!(2024-08-04 06:00 UTC), &observer);
assert!(
(h.altitude.degrees() - 77.906_675).abs() < 1.0 / 60.0,
"alt {}",
h.altitude.degrees()
);
assert!(
(h.azimuth.degrees() - 307.877_201).abs() < 0.08,
"az {}",
h.azimuth.degrees()
);
}
#[test]
fn azimuth_stays_normalized_west_of_meridian() {
let h = alt_az(
eq(180.0, -10.0),
datetime!(2024-01-01 12:00 UTC),
&site(0.0, 0.0, 0.0),
);
let az = h.azimuth.degrees();
assert!((0.0..360.0).contains(&az), "az {az}");
}
#[test]
fn zenith_azimuth_is_a_meridian_side() {
let observer = site(45.0, 0.0, 0.0);
let target = eq(0.0, 45.0);
let h = alt_az(target, datetime!(2024-03-20 12:00 UTC), &observer);
if h.altitude.degrees() > 89.9 {
let az = h.azimuth.degrees();
assert!(az == 0.0 || az == 180.0, "zenith az {az}");
}
}
#[test]
fn polar_observer_stays_in_range() {
let h = alt_az(
eq(37.954_56, 89.264_11),
datetime!(2024-06-21 00:00 UTC),
&site(89.9, 0.0, 0.0),
);
assert!((-90.0..=90.0).contains(&h.altitude.degrees()));
assert!((0.0..360.0).contains(&h.azimuth.degrees()));
}
#[test]
fn horizon_target_survives_acos_domain() {
let h = alt_az(
eq(90.0, 0.0),
datetime!(2024-03-20 06:00 UTC),
&site(0.0, 0.0, 0.0),
);
assert!((-90.0..=90.0).contains(&h.altitude.degrees()));
assert!((0.0..360.0).contains(&h.azimuth.degrees()));
}