This commit is contained in:
Austen Adler 2023-03-19 23:31:24 -04:00
parent bef1fec27c
commit 88fb2e0770
2 changed files with 63 additions and 97 deletions

View File

@ -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<Self, Self::Err> {
// DMM::parse(i).map_err(|_| ()).map(|(_, ret)| ret)
// }
// }
impl TryInto<LatLon> for Coordinate {
type Error = ();
fn try_into(self) -> Result<LatLon, Self::Error> {
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<LatLon> for Coordinate {
type Error = Infallible;
fn try_from(value: LatLon) -> Result<Self, Self::Error> {
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,
},
))

View File

@ -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<LatLon> for Coordinate {
fn try_into(self) -> Result<LatLon, Self::Error> {
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<dms::Coordinate> for Coordinate {
Self::DMS(c)
}
}
// impl From<dmm::Coordinate> for Coordinate {
// fn from(c: dmm::Coordinate) -> Self {
// Self::DMM(c)
// }
// }
impl From<dmm::Coordinate> for Coordinate {
fn from(c: dmm::Coordinate) -> Self {
Self::DMM(c)
}
}
impl From<utm::Coordinate> for Coordinate {
fn from(c: utm::Coordinate) -> Self {
Self::UTM(c)