added binary to generate landmarks from geojson file
This commit is contained in:
parent
1067c6a514
commit
a2cb9520cc
2 changed files with 109 additions and 0 deletions
94
src/bin/gen_landmarks_geojson.rs
Normal file
94
src/bin/gen_landmarks_geojson.rs
Normal 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");
|
||||
}
|
||||
|
|
@ -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]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue