From 2c410ecdfebc920710b67e3288404aae2c36bac9 Mon Sep 17 00:00:00 2001 From: frederic wagner Date: Thu, 21 Jul 2022 11:17:57 +0200 Subject: [PATCH] preparing for interest points --- apps/gipy/TODO | 4 +- apps/gipy/gpconv/Cargo.lock | 297 ++++++++++++++++++++++++++++++++- apps/gipy/gpconv/Cargo.toml | 1 + apps/gipy/gpconv/README_gpc.md | 58 +++++++ apps/gipy/gpconv/src/main.rs | 117 ++++++++++++- apps/gipy/gpconv/src/osm.rs | 51 +++++- 6 files changed, 515 insertions(+), 13 deletions(-) create mode 100644 apps/gipy/gpconv/README_gpc.md diff --git a/apps/gipy/TODO b/apps/gipy/TODO index f0ccbd299..bad276a60 100644 --- a/apps/gipy/TODO +++ b/apps/gipy/TODO @@ -1,12 +1,14 @@ - water points ---> we group them following path by groups of cst_size and record segments ids marking limits +- split on points with comments + - turn off gps when moving to next waypoint - meters seem to be a bit too long - buzzing does not work nicely - -> is_list seems fishy + -> is_lost seems fishy - store several tracks - display average speed diff --git a/apps/gipy/gpconv/Cargo.lock b/apps/gipy/gpconv/Cargo.lock index da2fdaac5..50bc76cb4 100644 --- a/apps/gipy/gpconv/Cargo.lock +++ b/apps/gipy/gpconv/Cargo.lock @@ -17,6 +17,23 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + +[[package]] +name = "anyhow" +version = "1.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb07d2053ccdbe10e2af2995a2f116c1330396493dc1269f6a91d0ae82e19704" + [[package]] name = "assert_approx_eq" version = "1.1.0" @@ -62,12 +79,39 @@ version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + [[package]] name = "bytes" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" +[[package]] +name = "bzip2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6afcd980b5f3a45017c57e57a2fcccbb351cc43a356ce117ef760ef8052b89b0" +dependencies = [ + "bzip2-sys", + "libc", +] + +[[package]] +name = "bzip2-sys" +version = "0.1.11+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + [[package]] name = "cc" version = "1.0.73" @@ -80,6 +124,19 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +dependencies = [ + "libc", + "num-integer", + "num-traits", + "time 0.1.44", + "winapi", +] + [[package]] name = "core-foundation" version = "0.9.3" @@ -96,6 +153,81 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "darling" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f2c43f534ea4b0b049015d00269734195e6d3f0f6635cb692251aca6f9f8b3c" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e91455b86830a1c21799d94524df0845183fa55bafd9aa137b01c7d1065fa36" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29b5acf0dea37a7f66f7b25d2c5e93fd46f8f6968b1a5d7a3e02e97768afc95a" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "derive_builder" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d13202debe11181040ae9063d739fa32cfcaaebe2275fe387703460ae2365b30" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66e616858f6187ed828df7c64a6d71720d83767a7f19740b2d1b6fe6327b36e5" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "derive_builder_macro" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58a94ace95092c5acb1e97a7e846b310cfbd499652f72297da7493f618a98d73" +dependencies = [ + "derive_builder_core", + "syn", +] + [[package]] name = "either" version = "1.6.1" @@ -121,6 +253,18 @@ dependencies = [ "version_check", ] +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + +[[package]] +name = "fallible-streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" + [[package]] name = "fastrand" version = "1.7.0" @@ -130,6 +274,16 @@ dependencies = [ "instant", ] +[[package]] +name = "flate2" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "fnv" version = "1.0.7" @@ -209,6 +363,17 @@ dependencies = [ "num-traits", ] +[[package]] +name = "getrandom" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", +] + [[package]] name = "gimli" version = "0.26.1" @@ -223,6 +388,7 @@ dependencies = [ "itertools", "lazy_static", "openstreetmap-api", + "osmio", "tokio", ] @@ -236,7 +402,7 @@ dependencies = [ "error-chain", "geo-types", "thiserror", - "time", + "time 0.3.11", "xml-rs", ] @@ -259,12 +425,30 @@ dependencies = [ "tracing", ] +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash", +] + [[package]] name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +[[package]] +name = "hashlink" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7249a3129cbc1ffccd74857f81464a323a152173cdb134e0fd81bc803b29facf" +dependencies = [ + "hashbrown 0.11.2", +] + [[package]] name = "hermit-abi" version = "0.1.19" @@ -345,6 +529,12 @@ dependencies = [ "tokio-native-tls", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.2.3" @@ -363,7 +553,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.12.3", ] [[package]] @@ -381,6 +571,12 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" +[[package]] +name = "iter-progress" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97059d64dd4e3a8e16696f6c0be50c1d5da3a709983f39b73fd7f84f120c5cd4" + [[package]] name = "itertools" version = "0.10.3" @@ -417,6 +613,16 @@ version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +[[package]] +name = "libsqlite3-sys" +version = "0.22.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290b64917f8b0cb885d9de0f9959fe1f775d7fa12f1da2db9001c1c8ab60f89d" +dependencies = [ + "pkg-config", + "vcpkg", +] + [[package]] name = "lock_api" version = "0.4.7" @@ -471,7 +677,7 @@ checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" dependencies = [ "libc", "log", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys", ] @@ -493,6 +699,16 @@ dependencies = [ "tempfile", ] +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.15" @@ -597,6 +813,28 @@ dependencies = [ "urlencoding", ] +[[package]] +name = "osmio" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0db40ae840afac7f6c710abf757bb76c6b95b4a34a20d55811ef70d30b3ea24f" +dependencies = [ + "anyhow", + "byteorder", + "bzip2", + "chrono", + "derive_builder", + "flate2", + "iter-progress", + "protobuf", + "quick-xml", + "rusqlite", + "separator", + "serde", + "serde_json", + "xml-rs", +] + [[package]] name = "parking_lot" version = "0.12.1" @@ -653,6 +891,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "protobuf" +version = "2.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70731852eec72c56d11226c8a5f96ad5058a3dab73647ca5f7ee351e464f2571" + [[package]] name = "quick-xml" version = "0.22.0" @@ -727,6 +971,21 @@ dependencies = [ "winreg", ] +[[package]] +name = "rusqlite" +version = "0.25.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c4b1eaf239b47034fb450ee9cdedd7d0226571689d8823030c4b6c2cb407152" +dependencies = [ + "bitflags", + "fallible-iterator", + "fallible-streaming-iterator", + "hashlink", + "libsqlite3-sys", + "memchr", + "smallvec", +] + [[package]] name = "rustc-demangle" version = "0.1.21" @@ -778,11 +1037,20 @@ dependencies = [ "libc", ] +[[package]] +name = "separator" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f97841a747eef040fcd2e7b3b9a220a7205926e60488e673d9e4926d27772ce5" + [[package]] name = "serde" version = "1.0.139" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0171ebb889e45aa68b44aee0859b3eede84c6f5f5c228e6f140c0b2a0a46cad6" +dependencies = [ + "serde_derive", +] [[package]] name = "serde_derive" @@ -849,6 +1117,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "syn" version = "1.0.98" @@ -894,6 +1168,17 @@ dependencies = [ "syn", ] +[[package]] +name = "time" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" +dependencies = [ + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi", +] + [[package]] name = "time" version = "0.3.11" @@ -1069,6 +1354,12 @@ dependencies = [ "try-lock", ] +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/apps/gipy/gpconv/Cargo.toml b/apps/gipy/gpconv/Cargo.toml index b6053a3ce..681c86c7e 100644 --- a/apps/gipy/gpconv/Cargo.toml +++ b/apps/gipy/gpconv/Cargo.toml @@ -11,3 +11,4 @@ itertools="*" openstreetmap-api="*" tokio={version="1", features=["full"]} lazy_static="*" +osmio="*" diff --git a/apps/gipy/gpconv/README_gpc.md b/apps/gipy/gpconv/README_gpc.md new file mode 100644 index 000000000..a881d01bf --- /dev/null +++ b/apps/gipy/gpconv/README_gpc.md @@ -0,0 +1,58 @@ +This file documents the .gpc file format. + +current version is version 2. + +every number is encoded in little endian order. + +# header + +We start by a header of 5 16bytes unsigned ints. + +- the first int is a marker with value 47490 +- second int is version of this file format +- third int is **NP** the number of points composing the path +- fourth int is **IP** the number of interest points bordering the path +- fifth int is **LP** the number of interest points as encountered when looping through the path (higher than previous int since some points can be met several times) + +# points + +We continue with an array of **2 NP** f64 containing +for each point its x and y coordinate. + +# interest points + +After that comes the storage for interest points. + +- we start by an array of **2 IP** f64 containing +the x and y coordinates of each interest point +- we continue with an **IP** u8 array named **IPOINTS** containing the id of the point's type. +you can see the `Interest` enum in `src/osm.rs` to know what int is what. +for example 0 is a Bakery and 1 is a water point. + +Now we need to store the relationship between segments and points. +The idea is that in a display phase we don't want to loop on all interest points +to figure out if they should appear on the map or not. +We'll use the fact that we now the segments we want to display and therefore we should only +need to display the points bordering these segments. + +- we store an array **LOOP** of **LP** u16 indices of interest points in **IPOINTS** + +while this is a contiguous array it contains points along the path grouped in buckets of 5 points. + +to figure out on which segments they are : + +- we store an array **STARTS** of **ceil(LP/5)** u16 indices of groups of segments. + +Segments are grouped by 3. +This array tells us on which group of segment is the first point of any bucket. + +## display algorithm + +If we want to display the interest points for the segments between 10 and 16 for example we proceed +as follows: + + * segments are grouped by 3 so instead of segment indices of 10..=16 we will look at group indices 10/3 ..= 16/3 so 3..=5 + * we do a binary search of the highest number below 3 in the **STARTS** array. we call *s* the obtained index + * we do a binary search of the smallest number above 5 in the **STARTS** array. we call *e* the obtained index + * we now loop on all buckets between *s* and *e* that is : on all indices *i* in `LOOP[(s*5)..=(e*5)]` + * display `IPOINTS[i]` diff --git a/apps/gipy/gpconv/src/main.rs b/apps/gipy/gpconv/src/main.rs index 95b21c63f..811a4c361 100644 --- a/apps/gipy/gpconv/src/main.rs +++ b/apps/gipy/gpconv/src/main.rs @@ -8,10 +8,10 @@ use gpx::read; use gpx::Gpx; mod osm; -use osm::InterestPoint; +use osm::{parse_osm_data, InterestPoint}; const KEY: u16 = 47490; -const FILE_VERSION: u16 = 1; +const FILE_VERSION: u16 = 2; #[derive(Debug, PartialEq, Clone, Copy)] pub struct Point { @@ -327,18 +327,57 @@ fn compress_coordinates(points: &[(i32, i32)]) -> Vec<(i16, i16)> { xdiffs.zip(ydiffs).collect() } -fn save_coordinates>(path: P, points: &[Point]) -> std::io::Result<()> { +fn save_gpc>(path: P, points: &[Point], buckets: &[Bucket]) -> std::io::Result<()> { let mut writer = BufWriter::new(File::create(path)?); eprintln!("saving {} points", points.len()); + + let mut unique_interest_points = Vec::new(); + let mut correspondance = HashMap::new(); + let interests_on_path = buckets + .iter() + .flat_map(|b| &b.points) + .map(|p| match correspondance.entry(*p) { + std::collections::hash_map::Entry::Occupied(o) => *o.get(), + std::collections::hash_map::Entry::Vacant(v) => { + let index = unique_interest_points.len(); + unique_interest_points.push(*p); + v.insert(index); + index + } + }) + .collect::>(); + writer.write_all(&KEY.to_le_bytes())?; writer.write_all(&FILE_VERSION.to_le_bytes())?; writer.write_all(&(points.len() as u16).to_le_bytes())?; + writer.write_all(&(unique_interest_points.len() as u16).to_le_bytes())?; + writer.write_all(&(interests_on_path.len() as u16).to_le_bytes())?; points .iter() .flat_map(|p| [p.x, p.y]) .try_for_each(|c| writer.write_all(&c.to_le_bytes()))?; + unique_interest_points + .iter() + .flat_map(|p| [p.point.x, p.point.y]) + .try_for_each(|c| writer.write_all(&c.to_le_bytes()))?; + + unique_interest_points + .iter() + .map(|p| p.interest.into()) + .try_for_each(|i: u8| writer.write_all(&i.to_le_bytes()))?; + + interests_on_path + .iter() + .map(|i| *i as u16) + .try_for_each(|i| writer.write_all(&i.to_le_bytes()))?; + + buckets + .iter() + .map(|b| b.start as u16) + .try_for_each(|i| writer.write_all(&i.to_le_bytes()))?; + Ok(()) } @@ -419,11 +458,11 @@ fn save_path(writer: &mut W, p: &[Point], stroke: &str) -> std::io::Re Ok(()) } -fn save_svg>( +fn save_svg<'a, P: AsRef, I: IntoIterator>( filename: P, p: &[Point], rp: &[Point], - interest_points: &HashSet, + interest_points: I, waypoints: &HashSet, ) -> std::io::Result<()> { let mut writer = BufWriter::new(std::fs::File::create(filename)?); @@ -514,6 +553,58 @@ fn detect_waypoints(points: &[Point]) -> HashSet { .collect::>() } +pub struct Bucket { + points: Vec, + start: usize, +} + +fn position_interests_along_path( + interests: &mut [InterestPoint], + path: &[Point], + d: f64, + buckets_size: usize, // final points are indexed in buckets + groups_size: usize, // how many segments are compacted together +) -> Vec { + interests.sort_unstable_by(|p1, p2| p1.point.x.partial_cmp(&p2.point.x).unwrap()); + // first compute for each segment a vec containing its nearby points + let mut positions = Vec::new(); + for segment in path.windows(2) { + let mut local_interests = Vec::new(); + let x0 = segment[0].x; + let x1 = segment[1].x; + let (xmin, xmax) = if x0 <= x1 { (x0, x1) } else { (x1, x0) }; + let i = interests.partition_point(|p| p.point.x < xmin - d); + let interests = &interests[i..]; + let i = interests.partition_point(|p| p.point.x <= xmax + d); + let interests = &interests[..i]; + for interest in interests { + if interest.point.distance_to_segment(&segment[0], &segment[1]) <= d { + local_interests.push(*interest); + } + } + positions.push(local_interests); + } + // fuse points on chunks of consecutive segments together + let grouped_positions = positions + .chunks(groups_size) + .map(|c| c.iter().flatten().unique().copied().collect::>()) + .collect::>(); + // now, group the points in buckets + let chunks = grouped_positions + .iter() + .enumerate() + .flat_map(|(i, points)| points.iter().map(move |p| (i, p))) + .chunks(buckets_size); + let mut buckets = Vec::new(); + for bucket_points in &chunks { + let mut bucket_points = bucket_points.peekable(); + let start = bucket_points.peek().unwrap().0; + let points = bucket_points.map(|(_, p)| *p).collect(); + buckets.push(Bucket { points, start }); + } + buckets +} + #[tokio::main] async fn main() { let input_file = std::env::args().nth(1).unwrap_or("m.gpx".to_string()); @@ -529,8 +620,18 @@ async fn main() { eprintln!("rdp would have had {}", rdp(&p, 0.00015).len()); eprintln!("rdp took {:?}", start.elapsed()); - save_coordinates("test.gpc", &rp).unwrap(); + let mut interests = parse_osm_data("isere.osm.pbf"); + let buckets = position_interests_along_path(&mut interests, &rp, 0.0005, 5, 3); // let i = get_openstreetmap_data(&rp).await; - let i = HashSet::new(); - save_svg("test.svg", &p, &rp, &i, &waypoints).unwrap(); + // let i = HashSet::new(); + save_svg( + "test.svg", + &p, + &rp, + buckets.iter().flat_map(|b| &b.points), + &waypoints, + ) + .unwrap(); + + save_gpc("test.gpc", &rp, &buckets).unwrap(); } diff --git a/apps/gipy/gpconv/src/osm.rs b/apps/gipy/gpconv/src/osm.rs index a70e7ff5d..6f5cdc4bc 100644 --- a/apps/gipy/gpconv/src/osm.rs +++ b/apps/gipy/gpconv/src/osm.rs @@ -1,10 +1,14 @@ use super::Point; +use itertools::Itertools; use lazy_static::lazy_static; use openstreetmap_api::{ types::{BoundingBox, Credentials}, Openstreetmap, }; +use osmio::prelude::*; +use osmio::OSMObjBase; use std::collections::{HashMap, HashSet}; +use std::path::Path; #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum Interest { @@ -21,7 +25,24 @@ pub enum Interest { Pharmacy, } -#[derive(Debug, PartialEq, Eq, Hash)] +impl Into for Interest { + fn into(self) -> u8 { + match self { + Interest::Bakery => 0, + Interest::DrinkingWater => 1, + Interest::Toilets => 2, + Interest::BikeShop => 3, + Interest::ChargingStation => 4, + Interest::Bank => 5, + Interest::Supermarket => 6, + Interest::Table => 7, + Interest::Artwork => 8, + Interest::Pharmacy => 9, + } + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub struct InterestPoint { pub point: Point, pub interest: Interest, @@ -128,3 +149,31 @@ async fn get_openstreetmap_data(points: &[(f64, f64)]) -> HashSet } interest_points } + +pub fn parse_osm_data>(path: P) -> Vec { + let reader = osmio::read_pbf(path).ok(); + reader + .map(|mut reader| { + let mut interests = Vec::new(); + for obj in reader.objects() { + match obj { + osmio::obj_types::ArcOSMObj::Node(n) => { + n.lat_lon_f64().map(|(lat, lon)| { + for p in n.tags().filter_map(move |(k, v)| { + Interest::new(k, v).map(|i| InterestPoint { + point: Point { x: lon, y: lat }, + interest: i, + }) + }) { + interests.push(p); + } + }); + } + osmio::obj_types::ArcOSMObj::Way(_) => {} + osmio::obj_types::ArcOSMObj::Relation(_) => {} + } + } + interests + }) + .unwrap_or_default() +}