diff --git a/spatial-coordinate-systems/src/dmm.rs b/spatial-coordinate-systems/src/dmm.rs index 2c19b1f..83b3f0f 100644 --- a/spatial-coordinate-systems/src/dmm.rs +++ b/spatial-coordinate-systems/src/dmm.rs @@ -4,11 +4,9 @@ use crate::{ }; use dms_coordinates::{Bearing, DMS}; use nom::{ - branch::alt, - character::complete::{self, space0, space1}, - combinator::{eof, map, map_opt, map_res, opt}, - number::complete::double, - sequence::{pair, tuple}, + character::complete::{self}, + combinator::{map, map_opt}, + sequence::tuple, IResult, }; use std::{convert::Infallible, str::FromStr}; @@ -42,98 +40,62 @@ impl FromStr for Coordinate { #[derive(PartialEq, Debug)] pub struct DMM { - pub degrees: i16, + pub degrees: i32, pub minutes: f64, pub direction: Direction, } -fn parse_dmm(i: &str) -> IResult<&str, DMM> { - map( - tuple(( - // Degrees - complete::i32, - optional_separator('°'), - // Minutes - parse_f64, - optional_separator('\''), - // Direction - parse_direction, - )), - |(degrees, (), minutes, (), direction)| { - let seconds = minutes.fract() * 60_f64; - let dms = DMS::new( +impl DMM { + pub fn parse(i: &str) -> IResult<&str, DMM> { + map( + tuple(( + // Degrees + complete::i32, + optional_separator('°'), + // Minutes + parse_f64, + optional_separator('\''), + // Direction + parse_direction, + )), + |(degrees, (), minutes, (), direction)| DMM { degrees, minutes, - seconds, - match direction { - Direction::North => Bearing::North, - Direction::South => Bearing::South, - Direction::East => Bearing::East, - Direction::West => Bearing::West, - }, - ); - }, - )(i) + direction, + }, + )(i) + } } -// impl DMM { -// pub fn parse(i: &str) -> IResult<&str, DMM> { -// map( -// tuple(( -// // Degrees -// complete::i16, -// optional_separator('°'), -// // Minutes -// double, -// optional_separator('\''), -// // Direction -// parse_direction, -// )), -// |(degrees, (), minutes, (), direction)| DMM { -// degrees, -// minutes, -// direction, -// }, -// )(i) -// } -// } - -// impl FromStr for DMM { -// type Err = (); - -// /// Recognizes DMS in the formats: -// /// -// /// * `40° 31' 21" N, 105° 5' 39" W` -// /// * `40 31 21 N, 105 5 39 W` -// /// -// /// ```rust -// /// use spatial_coordinate_systems::dmm::DMM; -// /// use spatial_coordinate_systems::Direction; -// /// use std::str::FromStr; -// /// -// /// assert_eq!(DMM::from_str("40 31.3 N").unwrap(), DMM { -// /// degrees: 40, -// /// minutes: 31.3_f64, -// /// direction: Direction::North, -// /// }); -// /// assert_eq!(DMM::from_str("40°31' N").unwrap(), DMM { -// /// degrees: 40, -// /// minutes: 31_f64, -// /// direction: Direction::North, -// /// }); -// /// ``` -// fn from_str(i: &str) -> Result { -// DMM::parse(i).map_err(|_| ()).map(|(_, ret)| ret) -// } -// } - impl TryInto for Coordinate { type Error = (); fn try_into(self) -> Result { LatLon::from( - self.0.degrees as f64 + self.0.minutes * 60.0_f64, - self.1.degrees as f64 + self.1.minutes * 60.0_f64, + DMS::new( + self.0.degrees, + self.0.minutes as i32, + self.0.minutes.fract() * 60_f64, + match self.0.direction { + Direction::North => Bearing::North, + Direction::South => Bearing::South, + Direction::East => Bearing::East, + Direction::West => Bearing::West, + }, + ) + .to_decimal_degrees(), + DMS::new( + self.1.degrees, + self.1.minutes as i32, + self.1.minutes.fract() * 60_f64, + match self.1.direction { + Direction::North => Bearing::North, + Direction::South => Bearing::South, + Direction::East => Bearing::East, + Direction::West => Bearing::West, + }, + ) + .to_decimal_degrees(), ) .ok_or(()) } @@ -143,15 +105,19 @@ impl TryFrom for Coordinate { type Error = Infallible; fn try_from(value: LatLon) -> Result { + let lat = DMS::from_decimal_degrees(value.lat, true); + let lon = DMS::from_decimal_degrees(value.lon, false); + Ok(Self( DMM { - degrees: value.lat as i16, - minutes: value.lat.fract() * 60_f64, + degrees: lat.degrees, + minutes: lat.minutes as f64 + lat.seconds / 60_f64, + // TODO: Fix the bearing information for these direction: Direction::North, }, DMM { - degrees: value.lon as i16, - minutes: value.lon.fract() * 60_f64, + degrees: lon.degrees, + minutes: lon.minutes as f64 + lon.seconds / 60_f64, direction: Direction::North, }, )) diff --git a/spatial-coordinate-systems/src/lib.rs b/spatial-coordinate-systems/src/lib.rs index 0d22b4f..8d45335 100644 --- a/spatial-coordinate-systems/src/lib.rs +++ b/spatial-coordinate-systems/src/lib.rs @@ -1,7 +1,7 @@ use std::str::FromStr; mod common; pub mod dd; -// pub mod dmm; +pub mod dmm; pub mod dms; pub mod plus; pub mod utm; @@ -38,7 +38,7 @@ impl Direction { pub enum Coordinate { DD(dd::Coordinate), DMS(dms::Coordinate), - // DMM(dmm::Coordinate), + DMM(dmm::Coordinate), UTM(utm::Coordinate), Plus(plus::Coordinate), } @@ -51,7 +51,7 @@ impl Coordinate { alt(( map(dd::Coordinate::parse, Coordinate::DD), map(dms::Coordinate::parse, Coordinate::DMS), - // map(dmm::Coordinate::parse, Coordinate::DMM), + map(dmm::Coordinate::parse, Coordinate::DMM), map(utm::Coordinate::parse, Coordinate::UTM), map(plus::Coordinate::parse, Coordinate::Plus), )), @@ -69,7 +69,7 @@ impl TryInto for Coordinate { fn try_into(self) -> Result { match self { Coordinate::DD(dd) => dd.try_into().or(Err(())), - // Coordinate::DMM(dm) => dm.try_into(), + Coordinate::DMM(dm) => dm.try_into(), Coordinate::DMS(dms) => dms.try_into(), Coordinate::UTM(utm) => utm.try_into(), Coordinate::Plus(plus) => plus.try_into(), @@ -87,11 +87,11 @@ impl From for Coordinate { Self::DMS(c) } } -// impl From for Coordinate { -// fn from(c: dmm::Coordinate) -> Self { -// Self::DMM(c) -// } -// } +impl From for Coordinate { + fn from(c: dmm::Coordinate) -> Self { + Self::DMM(c) + } +} impl From for Coordinate { fn from(c: utm::Coordinate) -> Self { Self::UTM(c)