use std::error::Error;
use osmgraph::api::{QueryEngine, OverpassResponse, Element};
use osmgraph::graph::{OSMGraph, OSMNode, OSMEdge, create_graph};
use petgraph::stable_graph::DefaultIx;
use petgraph::graph::Edge;
use plotters::prelude::*;
fn display(image_location: &str, graph: OSMGraph) -> Result<(), Box<dyn std::error::Error>> {
let nodes: Vec<OSMNode> = graph
.raw_nodes()
.iter().map(|node| node.weight.clone())
.collect();
let min_lat: f64 = nodes.iter().map(|node| node.lat()).min_by(|a, b| a.total_cmp(b)).unwrap();
let mut max_lat: f64 = nodes.iter().map(|node| node.lat()).max_by(|a, b| a.total_cmp(b)).unwrap();
let d_lat: f64 = max_lat - min_lat;
let min_lon: f64 = nodes.iter().map(|node| node.lon()).min_by(|a, b| a.total_cmp(b)).unwrap();
let mut max_lon: f64 = nodes.iter().map(|node| node.lon()).max_by(|a, b| a.total_cmp(b)).unwrap();
let d_lon: f64 = max_lon - min_lon;
match d_lat > d_lon {
true => max_lon = min_lon + d_lat,
false => max_lat = min_lat + d_lon
}
let root = BitMapBackend::new(image_location, (3000, 3000)).into_drawing_area();
root.fill(&WHITE)?;
let mut chart = ChartBuilder::on(&root)
.caption("Map", ("sans-serif", 50))
.margin(20)
.x_label_area_size(30)
.y_label_area_size(30)
.build_cartesian_2d(min_lon..max_lon, min_lat..max_lat)?;
chart.configure_mesh()
.x_labels(10)
.y_labels(10)
.disable_mesh()
.draw()?;
chart.draw_series(
nodes.iter().map(|node| {
Circle::new((node.lon(), node.lat()), 1, ShapeStyle::from(&RED).filled())
}),
)?;
let edges: &[Edge<OSMEdge, DefaultIx>] = graph.raw_edges();
chart.draw_series(
edges.iter().map(|edge| {
let source: &OSMNode = graph
.node_weight(edge.source())
.ok_or("Could not find node that edge references")
.expect("Could not find node that edge references");
let target: &OSMNode = graph
.node_weight(edge.target())
.ok_or("Could not find node that edge references")
.expect("Could not find node that edge references");
PathElement::new(
vec![(source.lon(), source.lat()), (target.lon(), target.lat())],
&BLACK,
)
}),
)?;
root.present()?;
Ok(())
}
fn query_and_save(filepath: &str) -> Result<OverpassResponse, Box<dyn Error>> {
let response = QueryEngine::new()
.query_place_blocking("Manhattan".to_string(), Some(7))
.expect("Could not query OSM!");
let json: OverpassResponse = serde_json::from_str(&response)?;
let _ = json.save_blocking(filepath)?;
Ok(json)
}
fn main() {
let image_save_location = "./map.png";
let graph_save_location = "./assets/manhattan_test.json";
let json: OverpassResponse = OverpassResponse::load_blocking(graph_save_location)
.unwrap_or_else(|_|
query_and_save(graph_save_location).expect("Was not able to query!")
);
println!("Parsed the json!");
let elements: &Vec<Element> = json.elements();
println!("{} elements in request", elements.len());
let g: OSMGraph = create_graph(elements)
.expect("Was not able to create graph from json!");
println!("Created graph with {} nodes and {} edges",
g.node_count(),
g.edge_count()
);
println!("Example node:\n {}", g.raw_nodes()[0].weight);
println!("Example edge:\n {}", g.raw_edges()[0].weight);
println!("Displaying to {}", image_save_location);
display(image_save_location, g).expect("Couldn't display graph!");
}