pub mod position;
pub use position::Position;
pub mod direction;
pub use direction::Direction;
#[inline]
#[allow(dead_code)]
pub(crate) fn canonicalize_azimuth(angle: qtty::Degrees) -> qtty::Degrees {
angle.normalize()
}
#[inline]
#[allow(dead_code)]
pub(crate) fn canonicalize_polar(angle: qtty::Degrees) -> qtty::Degrees {
let wrapped = angle.wrap_signed(); let v = wrapped.value();
if v > 90.0 {
qtty::Degrees::new(180.0 - v)
} else if v < -90.0 {
qtty::Degrees::new(-180.0 - v)
} else {
wrapped
}
}
#[inline]
pub(crate) fn xyz_to_polar_azimuth(x: f64, y: f64, z: f64) -> (qtty::Degrees, qtty::Degrees) {
use qtty::Degrees;
let z_clamped = z.clamp(-1.0, 1.0);
let polar = Degrees::new(z_clamped.asin().to_degrees());
let azimuth = Degrees::new(y.atan2(x).to_degrees()).normalize();
(polar, azimuth)
}
#[inline]
pub(crate) fn angular_separation_impl(
polar1: qtty::Degrees,
azimuth1: qtty::Degrees,
polar2: qtty::Degrees,
azimuth2: qtty::Degrees,
) -> qtty::Degrees {
use qtty::{Degree, Radian, Radians};
let az1 = azimuth1.to::<Radian>();
let po1 = polar1.to::<Radian>();
let az2 = azimuth2.to::<Radian>();
let po2 = polar2.to::<Radian>();
let x = (po1.cos() * po2.sin()) - (po1.sin() * po2.cos() * (az2 - az1).cos());
let y = po2.cos() * (az2 - az1).sin();
let z = (po1.sin() * po2.sin()) + (po1.cos() * po2.cos() * (az2 - az1).cos());
let angle_rad = (x * x + y * y).sqrt().atan2(z);
Radians::new(angle_rad).to::<Degree>()
}