From a2cb9520ccdd80936c4ca9b87e18a69c59b10fc4 Mon Sep 17 00:00:00 2001 From: Johannes Erwerle Date: Thu, 15 Sep 2022 16:29:42 +0200 Subject: [PATCH] added binary to generate landmarks from geojson file --- src/bin/gen_landmarks_geojson.rs | 94 ++++++++++++++++++++++++++++++++ src/coordinates.rs | 15 +++++ 2 files changed, 109 insertions(+) create mode 100644 src/bin/gen_landmarks_geojson.rs diff --git a/src/bin/gen_landmarks_geojson.rs b/src/bin/gen_landmarks_geojson.rs new file mode 100644 index 0000000..32c8fe0 --- /dev/null +++ b/src/bin/gen_landmarks_geojson.rs @@ -0,0 +1,94 @@ +use bincode; +use clap::Parser; +use fapra_osm_2::alt::{Landmark, LandmarkSet}; +use fapra_osm_2::utils::load_graph; +use fapra_osm_2::coordinates::{RadianCoordinate, DegreeCoordinate}; +use std::fs::{read_to_string, File}; +use std::io::prelude::*; +use std::process::exit; +use geojson::{GeoJson, Value}; + +#[derive(Parser, Debug)] +#[clap(author, version, about, long_about=None)] +struct Args { + /// the FMI file to load + #[clap(short, long)] + graph: String, + + /// the file to which to write the landmarks + #[clap(short, long)] + output: String, + + /// the geojson file from which to load the landmarks + #[clap(short, long)] + geojson: String, +} + +fn main() { + let args = Args::parse(); + + let graph = load_graph(&args.graph); + + let mut output = match File::create(args.output.clone()) { + Ok(f) => f, + Err(e) => { + println!("Error while creating the file {}: {}", args.output, e); + exit(2) + } + }; + + let geojson_str = match read_to_string(args.geojson.clone()) { + Ok(f) => f, + Err(e) => { + println!("Error while opening the file {}: {}", args.geojson, e); + exit(2) + } + }; + + let geojson: GeoJson = geojson_str.parse::().unwrap(); + + let features = match geojson { + GeoJson::FeatureCollection(features) => features.features, + _ => { + println!("Expected a FeatureCollection, didn't get one!"); + exit(3); + } + }; + + + // parse the GeoJSON + let mut points: Vec = Vec::new(); + + for feature in features.iter() { + if let Some(geometry) = &feature.geometry { + if let Value::Point(point) = &geometry.value { + if let Ok(coordinate) = DegreeCoordinate::from_geojson_position(point.clone()) { + points.push(RadianCoordinate::from(coordinate)); + continue; + } + } + } + println!("failed to parse {:?}", feature); + exit(4); + } + + let mut set = LandmarkSet::default(); + + // generate the landmarks + for position in points.iter() { + if let Some(node) = graph.get_nearest_node(*position) { + let landmark = Landmark::generate(*node, &graph); + set.landmarks.push(landmark); + } else { + println!("Could not find a nearest node to {:?}", position); + exit(5); + } + } + + + let encoded = bincode::serialize(&set).unwrap(); + + output + .write_all(&encoded) + .expect("Error while writing LandmarkSet data"); +} diff --git a/src/coordinates.rs b/src/coordinates.rs index 560ef87..0c7fbd5 100644 --- a/src/coordinates.rs +++ b/src/coordinates.rs @@ -51,6 +51,7 @@ impl From for DegreeCoordinate { } } + impl RadianCoordinate { /// Builds a RadianCoordinate from latitude and longitude given in /// degrees. @@ -154,6 +155,20 @@ impl DegreeCoordinate { Ok(DegreeCoordinate{lat, lon}) } + + + /// tries to parse a DegreeCoordinate from a GeoJSON Position + pub fn from_geojson_position(position: geojson::Position) -> Result { + + if position.len() != 2 { + return Err("String has more than 2 values".to_string()); + } + + let lat = position[1]; + let lon = position[0]; + + Ok(DegreeCoordinate { lat, lon }) + } } /// normalizes longitude values given in radians to the range (-PI, PI]