1use crate::Error;
4use ordered_float::OrderedFloat;
5
6pub const ZERO: OrderedFloat<f64> = OrderedFloat(0.0);
11
12const MINUTES_PER_DEGREE: f64 = 60.0;
17const SECONDS_PER_MINUTE: f64 = 60.0;
18const SECONDS_PER_DEGREE: f64 = MINUTES_PER_DEGREE * SECONDS_PER_MINUTE;
19
20pub(crate) const fn from_degrees_minutes_seconds(
24 degrees: i32,
25 minutes: u32,
26 seconds: f32,
27) -> Result<OrderedFloat<f64>, Error> {
28 if minutes >= MINUTES_PER_DEGREE as u32 {
29 return Err(Error::InvalidMinutes(minutes));
30 }
31 if seconds.is_sign_negative() || seconds >= SECONDS_PER_MINUTE as f32 {
32 return Err(Error::InvalidSeconds(seconds));
33 }
34 Ok(OrderedFloat(to_decimal_degrees(degrees, minutes, seconds)))
35}
36
37pub(crate) const fn to_decimal_degrees(degrees: i32, minutes: u32, seconds: f32) -> f64 {
43 let abs_degs = degrees.abs() as f64;
44 let fmins = minutes as f64 / MINUTES_PER_DEGREE;
45 let fsecs = seconds as f64 / SECONDS_PER_DEGREE;
46 let float = abs_degs + fmins + fsecs;
47 let float = if degrees.is_negative() { -float } else { float };
49 float
50}
51
52pub(crate) const fn to_degrees_minutes_seconds(angle: OrderedFloat<f64>) -> (i32, u32, f32) {
59 let float = angle.0;
60 let negative = float < 0.0;
61 let abs = if negative { -float } else { float };
62 let degrees_abs = abs.trunc() as i32;
63 let remainder = abs.fract() * MINUTES_PER_DEGREE;
64 let minutes = remainder.trunc() as u32;
65 let seconds = (remainder.fract() * SECONDS_PER_MINUTE) as f32;
66 let degrees = if negative { -degrees_abs } else { degrees_abs };
67 (degrees, minutes, seconds)
68}