Normalize dms and dmm to always have positive degrees

This commit is contained in:
Austen Adler 2023-04-22 13:23:20 -04:00
parent 80ca551fa9
commit c5b8b360ed
5 changed files with 54 additions and 23 deletions

View File

@ -36,6 +36,15 @@ pub fn parse_direction(i: &str) -> IResult<&str, Direction> {
))(i)
}
/// Changes degrees to a positive number and flips the direction if required
pub fn normalize_degrees_direction(degrees: i16, direction: Direction) -> (i16, Direction) {
if degrees < 0 {
(-degrees, direction.inverse())
} else {
(degrees, direction)
}
}
pub fn parse_f64(i: &str) -> IResult<&str, f64> {
map_opt(
tuple((

View File

@ -1,5 +1,5 @@
use crate::{
common::{optional_separator, parse_direction, parse_f64},
common::{normalize_degrees_direction, optional_separator, parse_direction, parse_f64},
Direction, Error, LatLon,
};
use nom::{
@ -95,16 +95,12 @@ impl DMM {
),
)),
|((degrees, minutes), _, direction)| {
let negate = direction == Direction::West || direction == Direction::South;
let (degrees, direction) = normalize_degrees_direction(degrees, direction);
Self {
degrees: degrees * if negate { -1 } else { 1 },
degrees,
minutes,
direction: if direction.is_lat() {
Direction::North
} else {
Direction::East
},
direction,
}
},
)(i)
@ -114,14 +110,19 @@ impl DMM {
let degrees = d as i16;
let minutes = d.fract() * 60_f64;
Self {
let (degrees, direction) = normalize_degrees_direction(
degrees,
minutes,
direction: if is_latitude {
if is_latitude {
Direction::North
} else {
Direction::East
},
);
Self {
degrees,
minutes,
direction,
}
}

View File

@ -1,5 +1,5 @@
use crate::{
common::{optional_separator, parse_direction, parse_f64},
common::{normalize_degrees_direction, optional_separator, parse_direction, parse_f64},
Direction, Error, LatLon,
};
use nom::{
@ -94,17 +94,13 @@ impl DMS {
),
)),
|((degrees, minutes, seconds), _, direction)| {
let negate = direction == Direction::West || direction == Direction::South;
let (degrees, direction) = normalize_degrees_direction(degrees, direction);
Self {
degrees: degrees * if negate { -1 } else { 1 },
degrees,
minutes,
seconds,
direction: if direction.is_lat() {
Direction::North
} else {
Direction::East
},
direction,
}
},
)(i)
@ -116,15 +112,20 @@ impl DMS {
let seconds = minutes.fract() * 60_f64;
let minutes = minutes as i16;
Self {
let (degrees, direction) = normalize_degrees_direction(
degrees,
minutes,
seconds,
direction: if is_latitude {
if is_latitude {
Direction::North
} else {
Direction::East
},
);
Self {
degrees,
minutes,
seconds,
direction,
}
}

View File

@ -61,6 +61,16 @@ impl Direction {
pub fn is_positive(&self) -> bool {
self == &Self::North || self == &Self::East
}
/// Flips the direction
pub fn inverse(&self) -> Self {
match self {
Direction::North => Direction::South,
Direction::South => Direction::North,
Direction::East => Direction::West,
Direction::West => Direction::East,
}
}
}
#[derive(Debug, PartialEq, Clone, EnumDiscriminants)]

View File

@ -149,6 +149,16 @@ mod tests {
"120000N1000000E"
);
assert_eq!(
Coordinate::from(LatLon::new(90.0_f64, 100.0_f64).unwrap()).0,
"900000N1000000E"
);
assert_eq!(
Coordinate::from(LatLon::new(-90.0_f64, 100.0_f64).unwrap()).0,
"900000S1000000E"
);
// p!("0° 0' N", DMS);
// p!("0° 0'N", DMS);
// p!("N 0° 0'", DMS);