Continue normalizing coordinate systems

This commit is contained in:
Austen Adler 2023-03-19 23:10:39 -04:00
parent 11e158b0e8
commit c9cc544802
6 changed files with 520 additions and 147 deletions

336
Cargo.lock generated
View File

@ -2,6 +2,21 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 3
[[package]]
name = "addr2line"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97"
dependencies = [
"gimli",
]
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]] [[package]]
name = "aead" name = "aead"
version = "0.5.1" version = "0.5.1"
@ -70,6 +85,12 @@ dependencies = [
"num-traits", "num-traits",
] ]
[[package]]
name = "assert_approx_eq"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c07dab4369547dbe5114677b33fbbf724971019f3818172d59a97a61c774ffd"
[[package]] [[package]]
name = "async-stream" name = "async-stream"
version = "0.3.4" version = "0.3.4"
@ -129,6 +150,21 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "backtrace"
version = "0.3.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca"
dependencies = [
"addr2line",
"cc",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
]
[[package]] [[package]]
name = "base64" name = "base64"
version = "0.20.0" version = "0.20.0"
@ -141,7 +177,7 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6aaf33151a6429fe9211d1b276eafdf70cdff28b071e76c0b0e1503221ea3744" checksum = "6aaf33151a6429fe9211d1b276eafdf70cdff28b071e76c0b0e1503221ea3744"
dependencies = [ dependencies = [
"num-bigint", "num-bigint 0.4.3",
"num-integer", "num-integer",
"num-traits", "num-traits",
] ]
@ -158,6 +194,16 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitvec"
version = "0.17.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41262f11d771fd4a61aa3ce019fca363b4b6c282fca9da2a31186d3965a47a5c"
dependencies = [
"either",
"radium",
]
[[package]] [[package]]
name = "block-buffer" name = "block-buffer"
version = "0.10.4" version = "0.10.4"
@ -237,7 +283,7 @@ dependencies = [
"hkdf", "hkdf",
"hmac", "hmac",
"percent-encoding", "percent-encoding",
"rand", "rand 0.8.5",
"sha2", "sha2",
"subtle", "subtle",
"time", "time",
@ -260,7 +306,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [ dependencies = [
"generic-array", "generic-array",
"rand_core", "rand_core 0.6.4",
"typenum", "typenum",
] ]
@ -338,6 +384,22 @@ dependencies = [
"subtle", "subtle",
] ]
[[package]]
name = "dms-coordinates"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec6b438cc34e673063a715ff761392e195278759fa5d882d6bc6b78e2e30d90d"
dependencies = [
"geo-types",
"gpx",
"initial_conditions",
"map_3d",
"rust-3d",
"serde",
"serde_derive",
"thiserror",
]
[[package]] [[package]]
name = "either" name = "either"
version = "1.8.1" version = "1.8.1"
@ -374,6 +436,16 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "error-chain"
version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc"
dependencies = [
"backtrace",
"version_check",
]
[[package]] [[package]]
name = "fastrand" name = "fastrand"
version = "1.9.0" version = "1.9.0"
@ -403,6 +475,12 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
[[package]] [[package]]
name = "futures" name = "futures"
version = "0.3.27" version = "0.3.27"
@ -491,6 +569,17 @@ dependencies = [
"version_check", "version_check",
] ]
[[package]]
name = "geo-types"
version = "0.7.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5f0b3068e1537a4b861ec3734f4aa9c317d537cf0845bf6fb6221973499d26c"
dependencies = [
"approx",
"num-traits",
"serde",
]
[[package]] [[package]]
name = "geoutils" name = "geoutils"
version = "0.5.1" version = "0.5.1"
@ -518,12 +607,32 @@ dependencies = [
"polyval", "polyval",
] ]
[[package]]
name = "gimli"
version = "0.27.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4"
[[package]] [[package]]
name = "glob" name = "glob"
version = "0.3.1" version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "gpx"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b03599b85866c88fd0125db7ca7a683be1550724918682c736c7893a399dc5e"
dependencies = [
"assert_approx_eq",
"error-chain",
"geo-types",
"thiserror",
"time",
"xml-rs",
]
[[package]] [[package]]
name = "h2" name = "h2"
version = "0.3.16" version = "0.3.16"
@ -669,6 +778,15 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "initial_conditions"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ddf16659f435e5c98d948694a97c33b6660c35adad199ab10362092a45ce921"
dependencies = [
"num 0.1.42",
]
[[package]] [[package]]
name = "inlinable_string" name = "inlinable_string"
version = "0.1.15" version = "0.1.15"
@ -768,6 +886,12 @@ dependencies = [
"tracing-subscriber", "tracing-subscriber",
] ]
[[package]]
name = "map_3d"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0fc1b6107fbd06c96e5e481fcf3e6575b873eb84f5b68f1f5706cde0fed42c4"
[[package]] [[package]]
name = "matchers" name = "matchers"
version = "0.1.0" version = "0.1.0"
@ -795,6 +919,15 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "miniz_oxide"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
dependencies = [
"adler",
]
[[package]] [[package]]
name = "mio" name = "mio"
version = "0.8.6" version = "0.8.6"
@ -847,6 +980,57 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "num"
version = "0.1.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e"
dependencies = [
"num-bigint 0.1.44",
"num-complex 0.1.43",
"num-integer",
"num-iter",
"num-rational 0.1.42",
"num-traits",
]
[[package]]
name = "num"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8536030f9fea7127f841b45bb6243b27255787fb4eb83958aa1ef9d2fdc0c36"
dependencies = [
"num-bigint 0.2.6",
"num-complex 0.2.4",
"num-integer",
"num-iter",
"num-rational 0.2.4",
"num-traits",
]
[[package]]
name = "num-bigint"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e63899ad0da84ce718c14936262a41cee2c79c981fc0a0e7c7beb47d5a07e8c1"
dependencies = [
"num-integer",
"num-traits",
"rand 0.4.6",
"rustc-serialize",
]
[[package]]
name = "num-bigint"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]] [[package]]
name = "num-bigint" name = "num-bigint"
version = "0.4.3" version = "0.4.3"
@ -858,6 +1042,26 @@ dependencies = [
"num-traits", "num-traits",
] ]
[[package]]
name = "num-complex"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b288631d7878aaf59442cffd36910ea604ecd7745c36054328595114001c9656"
dependencies = [
"num-traits",
"rustc-serialize",
]
[[package]]
name = "num-complex"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95"
dependencies = [
"autocfg",
"num-traits",
]
[[package]] [[package]]
name = "num-integer" name = "num-integer"
version = "0.1.45" version = "0.1.45"
@ -868,6 +1072,41 @@ dependencies = [
"num-traits", "num-traits",
] ]
[[package]]
name = "num-iter"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.1.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee314c74bd753fc86b4780aa9475da469155f3848473a261d2d18e35245a784e"
dependencies = [
"num-bigint 0.1.44",
"num-integer",
"num-traits",
"rustc-serialize",
]
[[package]]
name = "num-rational"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef"
dependencies = [
"autocfg",
"num-bigint 0.2.6",
"num-integer",
"num-traits",
]
[[package]] [[package]]
name = "num-traits" name = "num-traits"
version = "0.2.15" version = "0.2.15"
@ -875,6 +1114,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"libm",
] ]
[[package]] [[package]]
@ -887,6 +1127,15 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "object"
version = "0.30.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.17.1" version = "1.17.1"
@ -983,7 +1232,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1181c94580fa345f50f19d738aaa39c0ed30a600d95cb2d3e23f94266f14fbf" checksum = "b1181c94580fa345f50f19d738aaa39c0ed30a600d95cb2d3e23f94266f14fbf"
dependencies = [ dependencies = [
"phf_shared", "phf_shared",
"rand", "rand 0.8.5",
] ]
[[package]] [[package]]
@ -1091,6 +1340,25 @@ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]]
name = "radium"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "def50a86306165861203e7f84ecffbbdfdea79f0e51039b33de1e952358c47ac"
[[package]]
name = "rand"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
dependencies = [
"fuchsia-cprng",
"libc",
"rand_core 0.3.1",
"rdrand",
"winapi",
]
[[package]] [[package]]
name = "rand" name = "rand"
version = "0.8.5" version = "0.8.5"
@ -1099,7 +1367,7 @@ checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [ dependencies = [
"libc", "libc",
"rand_chacha", "rand_chacha",
"rand_core", "rand_core 0.6.4",
] ]
[[package]] [[package]]
@ -1109,9 +1377,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [ dependencies = [
"ppv-lite86", "ppv-lite86",
"rand_core", "rand_core 0.6.4",
] ]
[[package]]
name = "rand_core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
dependencies = [
"rand_core 0.4.2",
]
[[package]]
name = "rand_core"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
[[package]] [[package]]
name = "rand_core" name = "rand_core"
version = "0.6.4" version = "0.6.4"
@ -1121,6 +1404,15 @@ dependencies = [
"getrandom", "getrandom",
] ]
[[package]]
name = "rdrand"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
dependencies = [
"rand_core 0.3.1",
]
[[package]] [[package]]
name = "redox_syscall" name = "redox_syscall"
version = "0.2.16" version = "0.2.16"
@ -1198,7 +1490,7 @@ dependencies = [
"num_cpus", "num_cpus",
"parking_lot", "parking_lot",
"pin-project-lite", "pin-project-lite",
"rand", "rand 0.8.5",
"ref-cast", "ref-cast",
"rocket_codegen", "rocket_codegen",
"rocket_http", "rocket_http",
@ -1258,6 +1550,17 @@ dependencies = [
"uncased", "uncased",
] ]
[[package]]
name = "rust-3d"
version = "0.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ce1e81ec1eec57188d13fdeb9fcdf961914eb0f57e3b40c723be3b9245de9bb"
dependencies = [
"bitvec",
"fnv",
"num 0.2.1",
]
[[package]] [[package]]
name = "rust-embed" name = "rust-embed"
version = "6.6.0" version = "6.6.0"
@ -1293,6 +1596,18 @@ dependencies = [
"walkdir", "walkdir",
] ]
[[package]]
name = "rustc-demangle"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
[[package]]
name = "rustc-serialize"
version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "0.36.10" version = "0.36.10"
@ -1447,6 +1762,7 @@ dependencies = [
name = "spatial-coordinate-systems" name = "spatial-coordinate-systems"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"dms-coordinates",
"nom", "nom",
"pluscodes", "pluscodes",
"thiserror", "thiserror",
@ -2095,6 +2411,12 @@ dependencies = [
"thiserror", "thiserror",
] ]
[[package]]
name = "xml-rs"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3"
[[package]] [[package]]
name = "xpin" name = "xpin"
version = "0.1.0" version = "0.1.0"

View File

@ -6,6 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
dms-coordinates = "1.1.0"
nom = "7.1.3" nom = "7.1.3"
pluscodes = "0.5.0" pluscodes = "0.5.0"
thiserror = "1.0.40" thiserror = "1.0.40"

View File

@ -1,3 +1,4 @@
use dms_coordinates::{Bearing, DMS};
use nom::{ use nom::{
branch::alt, branch::alt,
bytes::complete::{tag_no_case, take_while1}, bytes::complete::{tag_no_case, take_while1},
@ -37,12 +38,20 @@ pub fn parse_direction(i: &str) -> IResult<&str, Direction> {
pub fn parse_f64(i: &str) -> IResult<&str, f64> { pub fn parse_f64(i: &str) -> IResult<&str, f64> {
map_opt( map_opt(
take_while1(|c: char| c.is_ascii_digit() || c == '-' || c == '.'), tuple((
|n: &str| n.parse::<f64>().ok(), opt(complete::char('-')),
take_while1(|c: char| c.is_ascii_digit() || c == '.'),
)),
|(neg, n_str): (Option<char>, &str)| {
n_str
.parse::<f64>()
.map(|n| n * if neg.is_some() { -1.0_f64 } else { 1.0_f64 })
.ok()
},
)(i) )(i)
} }
#[cfg(tests)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
@ -52,5 +61,7 @@ mod tests {
assert_eq!(parse_f64("1.0"), Ok(("", 1.0_f64))); assert_eq!(parse_f64("1.0"), Ok(("", 1.0_f64)));
assert_eq!(parse_f64("1.0e2"), Ok(("e2", 1.0_f64))); assert_eq!(parse_f64("1.0e2"), Ok(("e2", 1.0_f64)));
assert_eq!(parse_f64("1.0x"), Ok(("x", 1.0_f64))); assert_eq!(parse_f64("1.0x"), Ok(("x", 1.0_f64)));
assert_eq!(parse_f64("-1.0x"), Ok(("x", -1.0_f64)));
assert_eq!(parse_f64("-1.0-x"), Ok(("-x", -1.0_f64)));
} }
} }

View File

@ -1,7 +1,8 @@
use crate::{ use crate::{
common::{optional_separator, parse_direction}, common::{optional_separator, parse_direction, parse_f64},
Direction, LatLon, Direction, LatLon,
}; };
use dms_coordinates::{Bearing, DMS};
use nom::{ use nom::{
branch::alt, branch::alt,
character::complete::{self, space0, space1}, character::complete::{self, space0, space1},
@ -46,56 +47,85 @@ pub struct DMM {
pub direction: Direction, pub direction: Direction,
} }
impl DMM { fn parse_dmm(i: &str) -> IResult<&str, DMM> {
pub fn parse(i: &str) -> IResult<&str, DMM> {
map( map(
tuple(( tuple((
// Degrees // Degrees
complete::i16, complete::i32,
optional_separator('°'), optional_separator('°'),
// Minutes // Minutes
double, parse_f64,
optional_separator('\''), optional_separator('\''),
// Direction // Direction
parse_direction, parse_direction,
)), )),
|(degrees, (), minutes, (), direction)| DMM { |(degrees, (), minutes, (), direction)| {
let seconds = minutes.fract() * 60_f64;
let dms = DMS::new(
degrees, degrees,
minutes, minutes,
direction, seconds,
match direction {
Direction::North => Bearing::North,
Direction::South => Bearing::South,
Direction::East => Bearing::East,
Direction::West => Bearing::West,
},
);
}, },
)(i) )(i)
} }
}
impl FromStr for DMM { // impl DMM {
type Err = (); // 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)
// }
// }
/// Recognizes DMS in the formats: // impl FromStr for DMM {
/// // type Err = ();
/// * `40° 31' 21" N, 105° 5' 39" W`
/// * `40 31 21 N, 105 5 39 W` // /// Recognizes DMS in the formats:
/// // ///
/// ```rust // /// * `40° 31' 21" N, 105° 5' 39" W`
/// use spatial_coordinate_systems::dmm::DMM; // /// * `40 31 21 N, 105 5 39 W`
/// use spatial_coordinate_systems::Direction; // ///
/// use std::str::FromStr; // /// ```rust
/// // /// use spatial_coordinate_systems::dmm::DMM;
/// assert_eq!(DMM::from_str("40 31.3 N").unwrap(), DMM { // /// use spatial_coordinate_systems::Direction;
/// degrees: 40, // /// use std::str::FromStr;
/// minutes: 31.3_f64, // ///
/// direction: Direction::North, // /// assert_eq!(DMM::from_str("40 31.3 N").unwrap(), DMM {
/// }); // /// degrees: 40,
/// assert_eq!(DMM::from_str("40°31' N").unwrap(), DMM { // /// minutes: 31.3_f64,
/// degrees: 40, // /// direction: Direction::North,
/// minutes: 31_f64, // /// });
/// direction: Direction::North, // /// assert_eq!(DMM::from_str("40°31' N").unwrap(), DMM {
/// }); // /// degrees: 40,
/// ``` // /// minutes: 31_f64,
fn from_str(i: &str) -> Result<Self, Self::Err> { // /// direction: Direction::North,
DMM::parse(i).map_err(|_| ()).map(|(_, ret)| ret) // /// });
} // /// ```
} // fn from_str(i: &str) -> Result<Self, Self::Err> {
// DMM::parse(i).map_err(|_| ()).map(|(_, ret)| ret)
// }
// }
impl TryInto<LatLon> for Coordinate { impl TryInto<LatLon> for Coordinate {
type Error = (); type Error = ();

View File

@ -1,7 +1,9 @@
use crate::{ use crate::{
common::{optional_separator, parse_direction}, common::{optional_separator, parse_direction, parse_f64},
Direction, LatLon, Direction, LatLon,
}; };
use dms_coordinates::Bearing;
pub use dms_coordinates::DMS;
use nom::{ use nom::{
branch::alt, branch::alt,
character::complete::{self, space0, space1}, character::complete::{self, space0, space1},
@ -18,10 +20,13 @@ pub struct Coordinate(pub DMS, pub DMS);
impl Coordinate { impl Coordinate {
pub fn parse(i: &str) -> IResult<&str, Self> { pub fn parse(i: &str) -> IResult<&str, Self> {
map_opt( map_opt(
tuple((DMS::parse, optional_separator(','), DMS::parse)), tuple((parse_dms, optional_separator(','), parse_dms)),
|(ns, _, ew)| { |(ns, _, ew)| {
// Ensure this is a north/south then east/west direction // Ensure this is a north/south then east/west direction
if ns.direction.is_lat() && ew.direction.is_lon() { if ns.bearing.is_northern()
|| ns.bearing.is_southern() && ew.bearing.is_eastern()
|| ew.bearing.is_western()
{
Some(Coordinate(ns, ew)) Some(Coordinate(ns, ew))
} else { } else {
None None
@ -31,6 +36,37 @@ impl Coordinate {
} }
} }
fn parse_dms(i: &str) -> IResult<&str, DMS> {
map(
tuple((
// Degrees
complete::i32,
optional_separator('°'),
// Minutes
complete::i32,
optional_separator('\''),
// Seconds
parse_f64,
optional_separator('"'),
// Direction
parse_direction,
)),
|(degrees, (), minutes, (), seconds, (), direction)| {
DMS::new(
degrees,
minutes,
seconds,
match direction {
Direction::North => Bearing::North,
Direction::South => Bearing::South,
Direction::East => Bearing::East,
Direction::West => Bearing::West,
},
)
},
)(i)
}
impl FromStr for Coordinate { impl FromStr for Coordinate {
type Err = (); type Err = ();
@ -39,82 +75,66 @@ impl FromStr for Coordinate {
} }
} }
#[derive(PartialEq, Debug)] // pub fn parse(i: &str) -> IResult<&str, DMS> {
pub struct DMS { // map(
pub degrees: i16, // tuple((
pub minutes: i16, // // Degrees
pub seconds: f64, // complete::i16,
pub direction: Direction, // optional_separator('°'),
} // // Minutes
// complete::i16,
// optional_separator('\''),
// // Seconds
// double,
// optional_separator('"'),
// // Direction
// parse_direction,
// )),
// |(degrees, (), minutes, (), seconds, (), direction)| DMS {
// degrees,
// minutes,
// seconds,
// direction,
// },
// )(i)
// }
impl DMS { // impl FromStr for DMS {
pub fn parse(i: &str) -> IResult<&str, DMS> { // type Err = ();
map(
tuple((
// Degrees
complete::i16,
optional_separator('°'),
// Minutes
complete::i16,
optional_separator('\''),
// Seconds
double,
optional_separator('"'),
// Direction
parse_direction,
)),
|(degrees, (), minutes, (), seconds, (), direction)| DMS {
degrees,
minutes,
seconds,
direction,
},
)(i)
}
}
impl FromStr for DMS { // /// Recognizes DMS in the formats:
type Err = (); // ///
// /// * `40° 31' 21" N, 105° 5' 39" W`
/// Recognizes DMS in the formats: // /// * `40 31 21 N, 105 5 39 W`
/// // ///
/// * `40° 31' 21" N, 105° 5' 39" W` // /// ```rust
/// * `40 31 21 N, 105 5 39 W` // /// use spatial_coordinate_systems::dms::DMS;
/// // /// use spatial_coordinate_systems::Direction;
/// ```rust // /// use std::str::FromStr;
/// use spatial_coordinate_systems::dms::DMS; // ///
/// use spatial_coordinate_systems::Direction; // /// assert_eq!(DMS::from_str("40 31 21 N").unwrap(), DMS {
/// use std::str::FromStr; // /// degrees: 40,
/// // /// minutes: 31,
/// assert_eq!(DMS::from_str("40 31 21 N").unwrap(), DMS { // /// seconds: 21_f64,
/// degrees: 40, // /// direction: Direction::North,
/// minutes: 31, // /// });
/// seconds: 21_f64, // /// assert_eq!(DMS::from_str("40°31' 21 \" N").unwrap(), DMS {
/// direction: Direction::North, // /// degrees: 40,
/// }); // /// minutes: 31,
/// assert_eq!(DMS::from_str("40°31' 21 \" N").unwrap(), DMS { // /// seconds: 21_f64,
/// degrees: 40, // /// direction: Direction::North,
/// minutes: 31, // /// });
/// seconds: 21_f64, // /// ```
/// direction: Direction::North, // fn from_str(i: &str) -> Result<Self, Self::Err> {
/// }); // DMS::parse(i).map_err(|_| ()).map(|(_, ret)| ret)
/// ``` // }
fn from_str(i: &str) -> Result<Self, Self::Err> { // }
DMS::parse(i).map_err(|_| ()).map(|(_, ret)| ret)
}
}
impl TryInto<LatLon> for Coordinate { impl TryInto<LatLon> for Coordinate {
type Error = (); type Error = ();
fn try_into(self) -> Result<LatLon, Self::Error> { fn try_into(self) -> Result<LatLon, Self::Error> {
Err(()) LatLon::from(self.0.to_decimal_degrees(), self.1.to_decimal_degrees()).ok_or(())
// LatLon::from(
// self.0.degrees as f64 + self.0.minutes * 60.0_f64,
// self.1.degrees as f64 + self.1.minutes * 60.0_f64,
// )
// .ok_or(())
} }
} }
@ -122,20 +142,9 @@ impl TryFrom<LatLon> for Coordinate {
type Error = (); type Error = ();
fn try_from(value: LatLon) -> Result<Self, Self::Error> { fn try_from(value: LatLon) -> Result<Self, Self::Error> {
Err(()) Ok(Self(
// Ok(Self( DMS::from_decimal_degrees(value.lat, true),
// DMS { DMS::from_decimal_degrees(value.lon, false),
// degrees: value.lat as i16, ))
// minutes: value.lat.fract() * 60_f64 as i16,
// seconds: value.lat.fract() * 3600_f64,
// direction: Direction::North,
// },
// DMS {
// degrees: value.lon as i16,
// minutes: value.lon.fract() * 60_f64 as i16,
// seconds: value.lon.fract() * 3600_f64,
// direction: Direction::North,
// },
// ))
} }
} }

View File

@ -3,12 +3,12 @@
use std::str::FromStr; use std::str::FromStr;
mod common; mod common;
pub mod dd; pub mod dd;
pub mod dmm; // pub mod dmm;
pub mod dms; pub mod dms;
pub mod plus; pub mod plus;
pub mod utm; pub mod utm;
use dmm::DMM; // use dmm::DMM;
use dms::DMS; use dms::DMS;
use nom::{ use nom::{
branch::alt, branch::alt,
@ -42,7 +42,7 @@ impl Direction {
pub enum Coordinate { pub enum Coordinate {
DD(dd::Coordinate), DD(dd::Coordinate),
DMS(dms::Coordinate), DMS(dms::Coordinate),
DM(dmm::Coordinate), // DM(dmm::Coordinate),
UTM(utm::Coordinate), UTM(utm::Coordinate),
Plus(plus::Coordinate), Plus(plus::Coordinate),
} }
@ -55,7 +55,7 @@ impl Coordinate {
alt(( alt((
map(dd::Coordinate::parse, Coordinate::DD), map(dd::Coordinate::parse, Coordinate::DD),
map(dms::Coordinate::parse, Coordinate::DMS), map(dms::Coordinate::parse, Coordinate::DMS),
map(dmm::Coordinate::parse, Coordinate::DM), // map(dmm::Coordinate::parse, Coordinate::DM),
map(utm::Coordinate::parse, Coordinate::UTM), map(utm::Coordinate::parse, Coordinate::UTM),
map(plus::Coordinate::parse, Coordinate::Plus), map(plus::Coordinate::parse, Coordinate::Plus),
)), )),