-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.rs
134 lines (122 loc) · 4.25 KB
/
main.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
extern crate log;
pub mod crs;
pub mod geofile;
pub mod geograph;
pub mod osm;
pub mod topo;
use crate::crs::crs_utils::epsg_4326;
use crate::geofile::feature::Feature;
use crate::geofile::gdal_geofile::{write_features_to_geofile, GdalDriverType};
use crate::geograph::geo_feature_graph::GeoFeatureGraph;
use crate::geograph::utils::build_geograph_from_lines;
use crate::osm::download::{sync_osm_data_to_file, WgsBoundingBox};
use crate::topo::topo::{calculate_topo, TopoParams};
use anyhow::anyhow;
use clap::Parser;
use rayon::prelude::*;
use serde::Deserialize;
use std::path::PathBuf;
use std::{fs::read_to_string, path::Path};
/// Calculate the TOPO metric over a ground truth and a proposal road map.
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
/// Path to the input config file.
#[arg(short, long)]
config_filepath: String,
}
#[derive(Deserialize, Debug)]
enum GroundTruthConfig {
Geofile { filepath: PathBuf },
Osm { bounding_box: WgsBoundingBox },
}
#[derive(Deserialize, Debug)]
struct Config {
proposal_geofile_path: PathBuf,
ground_truth: GroundTruthConfig,
topo_params: TopoParams,
data_dir: PathBuf,
}
fn get_ground_truth_ways_from_osm(
bounding_box: &WgsBoundingBox,
data_dir: &PathBuf,
) -> anyhow::Result<Vec<geo::LineString>> {
log::info!("Syncing OSM data for bounding box {:?}", bounding_box);
let osm_filepath = sync_osm_data_to_file(&bounding_box, &data_dir)?;
log::info!("Reading OSM ways");
osm::conversion::read_osm_roads_from_file(&osm_filepath)
}
fn try_main() -> anyhow::Result<()> {
if std::env::var("RUST_LOG").is_err() {
std::env::set_var("RUST_LOG", "info")
}
let args = Args::try_parse()?;
if !Path::new(&args.config_filepath).exists() {
return Err(anyhow!("Config file {} not found", &args.config_filepath));
}
let config_contents = read_to_string(args.config_filepath)?;
let config: Config = serde_yaml::from_str(&config_contents)?;
let mut ground_truth_graph: GeoFeatureGraph<petgraph::Undirected> = match config.ground_truth {
GroundTruthConfig::Osm { bounding_box } => {
let ground_truth_ways =
get_ground_truth_ways_from_osm(&bounding_box, &config.data_dir)?;
let mut graph = build_geograph_from_lines(ground_truth_ways)?;
graph.crs = epsg_4326();
graph
}
GroundTruthConfig::Geofile { filepath } => GeoFeatureGraph::load_from_geofile(&filepath)?,
};
log::info!(
"Read ground truth graph with {} edges",
ground_truth_graph.edge_graph().edge_count()
);
let mut proposal_graph = GeoFeatureGraph::load_from_geofile(&config.proposal_geofile_path)?;
log::info!(
"Read proposal graph with {} edges",
proposal_graph.edge_graph().edge_count()
);
let geojson_dump_filepath = config.data_dir.join("ground_truth.geojson");
// Write the ground truth to file for reference.
log::info!(
"Writing ground truth edges to GeoJSON to {:?}",
&geojson_dump_filepath
);
geofile::geojson::write_lines_to_geojson(
&ground_truth_graph.edge_geometries(),
&geojson_dump_filepath,
)?;
topo::preprocessing::ensure_gt_proposal_in_same_projected_crs(
&mut ground_truth_graph,
&mut proposal_graph,
)?;
let topo_result = calculate_topo(&proposal_graph, &ground_truth_graph, &config.topo_params)?;
log::info!("{:?}", topo_result.f1_score_result);
write_features_to_geofile(
&topo_result
.proposal_nodes
.par_iter()
.map(|node| Feature::from(node))
.collect(),
&config.data_dir.join("proposal_nodes.gpkg"),
Some(&proposal_graph.crs),
GdalDriverType::GeoPackage.name(),
)?;
write_features_to_geofile(
&topo_result
.ground_truth_nodes
.par_iter()
.map(|node| Feature::from(node))
.collect(),
&config.data_dir.join("ground_truth_nodes.gpkg"),
Some(&ground_truth_graph.crs),
GdalDriverType::GeoPackage.name(),
)?;
Ok(())
}
fn main() {
env_logger::init();
if let Err(e) = try_main() {
eprintln!("Error: {:?}", e);
std::process::exit(1)
}
}