#[must_use]
pub fn normalize_angle(radians: f64) -> f64 {
let normalized = (radians + std::f64::consts::PI).rem_euclid(2.0 * std::f64::consts::PI)
- std::f64::consts::PI;
if normalized <= -std::f64::consts::PI {
std::f64::consts::PI
} else {
normalized
}
}
#[must_use]
pub fn planar_distance(from: (f64, f64), to: (f64, f64)) -> f64 {
(to.0 - from.0).hypot(to.1 - from.1)
}
#[cfg(test)]
mod tests {
use super::{normalize_angle, planar_distance};
use std::f64::consts::{FRAC_PI_2, PI};
#[test]
fn angles_inside_the_interval_are_unchanged() {
assert_eq!(normalize_angle(0.0), 0.0);
assert_eq!(normalize_angle(FRAC_PI_2), FRAC_PI_2);
assert_eq!(normalize_angle(-FRAC_PI_2), -FRAC_PI_2);
}
#[test]
fn angles_outside_the_interval_wrap_into_it() {
assert!((normalize_angle(3.0 * PI) - PI).abs() < 1e-12);
assert!((normalize_angle(2.0 * PI + FRAC_PI_2) - FRAC_PI_2).abs() < 1e-12);
assert!((normalize_angle(-2.0 * PI - FRAC_PI_2) + FRAC_PI_2).abs() < 1e-12);
}
#[test]
fn both_bounds_normalize_to_positive_pi() {
assert_eq!(normalize_angle(PI), PI);
assert_eq!(normalize_angle(-PI), PI);
assert_eq!(normalize_angle(3.0 * PI), normalize_angle(-PI));
}
#[test]
fn planar_distance_is_symmetric_and_zero_on_the_same_point() {
assert_eq!(planar_distance((1.5, -2.0), (1.5, -2.0)), 0.0);
assert_eq!(planar_distance((0.0, 0.0), (3.0, 4.0)), 5.0);
assert_eq!(
planar_distance((3.0, 4.0), (0.0, 0.0)),
planar_distance((0.0, 0.0), (3.0, 4.0))
);
}
}