added binary to generate landmarks from geojson file

This commit is contained in:
Johannes Erwerle 2022-09-15 16:29:42 +02:00
parent 1067c6a514
commit a2cb9520cc
2 changed files with 109 additions and 0 deletions

View file

@ -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::<GeoJson>().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<RadianCoordinate> = 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");
}

View file

@ -51,6 +51,7 @@ impl From<RadianCoordinate> 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<Self, String> {
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]