diff --git a/grids/grid_3x3.fmi b/grids/grid_3x3.fmi new file mode 100644 index 0000000..ac0a31f --- /dev/null +++ b/grids/grid_3x3.fmi @@ -0,0 +1,25 @@ +7 +16 +0 -90 180 +1 -90 -60.00000000000001 +2 -90 59.999999999999986 +3 -30.000000000000004 180 +4 -30.000000000000004 59.999999999999986 +5 29.999999999999993 180 +6 29.999999999999993 -60.00000000000001 +0 2 0 +0 1 0 +0 3 6671695 +1 0 0 +1 2 0 +2 1 0 +2 0 0 +2 4 6671695 +3 4 10806007 +3 5 6671695 +3 0 6671695 +4 3 10806007 +4 2 6671695 +5 6 10806007 +5 3 6671695 +6 5 10806007 diff --git a/routes/10x10_1.json b/routes/10x10_1.json new file mode 100644 index 0000000..7d08745 --- /dev/null +++ b/routes/10x10_1.json @@ -0,0 +1 @@ +[{"source":51,"destination":11}] diff --git a/routes/3x3_1.json b/routes/3x3_1.json new file mode 100644 index 0000000..7f74b99 --- /dev/null +++ b/routes/3x3_1.json @@ -0,0 +1 @@ +[{"source":2,"destination":5}] diff --git a/src/bin/generate_grid.rs b/src/bin/generate_grid.rs index 3478bf0..a8dd190 100644 --- a/src/bin/generate_grid.rs +++ b/src/bin/generate_grid.rs @@ -15,6 +15,15 @@ struct Args { /// the output file to write the grid to #[clap(short, long)] output: String, + + + /// the latitude resolution + #[clap(short, long)] + lat: usize, + + /// the longitude resolution + #[clap(short, long)] + lon: usize, } fn main() { @@ -47,7 +56,7 @@ fn main() { println!("{:?}", coasts.polygons[0].bbox); - let grid = GridGraph::generate_regular_grid(10, 10, Some(&coasts)); + let grid = GridGraph::generate_regular_grid(args.lat, args.lon, Some(&coasts)); // let grid = GridGraph::generate_regular_grid(3, 4, None); match grid.write_fmi_file(output) { diff --git a/src/bin/performance.rs b/src/bin/performance.rs index e84ba38..39bf722 100644 --- a/src/bin/performance.rs +++ b/src/bin/performance.rs @@ -93,7 +93,7 @@ fn main() { let source = astar.graph.nodes[query.source]; let destination = astar.graph.nodes[query.destination]; - let _result = astar.shortest_path(&source, &destination, estimate_haversine); + let _result = astar.shortest_path(&source, &destination, estimate_latitude); } let elapsed = start.elapsed(); @@ -109,13 +109,13 @@ fn main() { let start = Instant::now(); for query in targets.iter() { - println!("working on {:?}", query); + // println!("working on {:?}", query); let source = astar.graph.nodes[query.source]; let destination = astar.graph.nodes[query.destination]; let result = astar.graph.shortest_path(&source, &destination); - println!("{}", result.unwrap().to_geojson()); + //println!("{}", result.unwrap().to_geojson()); } let elapsed = start.elapsed(); diff --git a/src/gridgraph.rs b/src/gridgraph.rs index 1291462..c7a00f9 100644 --- a/src/gridgraph.rs +++ b/src/gridgraph.rs @@ -1,16 +1,16 @@ use crate::coordinates::{DegreeCoordinate, RadianCoordinate}; use crate::polygonset::PolygonSet; +use crate::utils::EARTH_RADIUS; use geojson::{Feature, FeatureCollection, Geometry, Position, Value}; +use rand::seq::SliceRandom; use serde::ser::{SerializeStruct, Serializer}; +use serde::{Deserialize, Serialize}; use std::cmp::Ordering; use std::collections::{BinaryHeap, HashMap}; use std::f64::consts::{FRAC_PI_2, PI, TAU}; use std::fs::File; use std::io::{BufRead, BufReader, Write}; use std::vec::Vec; -use crate::utils::EARTH_RADIUS; -use rand::seq::SliceRandom; -use serde::{Serialize, Deserialize}; /// Type for all edge costs /// Allows for easy adjustments for bigger/smaller number types if that is @@ -134,8 +134,6 @@ impl Route { } impl GridGraph { - - /// selects a single random graph node. pub fn get_random_node(&self) -> Option<&GraphNode> { let mut rng = rand::thread_rng(); @@ -143,14 +141,11 @@ impl GridGraph { self.nodes.choose(&mut rng) } - /// selects up to `amount` random but distinct nodes from the graph. - pub fn get_random_nodes(&self, amount: usize) -> Vec<&GraphNode>{ - + pub fn get_random_nodes(&self, amount: usize) -> Vec<&GraphNode> { let mut rng = rand::thread_rng(); self.nodes.choose_multiple(&mut rng, amount).collect() - } /// calculates the shortest path from the start node to the end node. @@ -169,7 +164,10 @@ impl GridGraph { // inverted cmp function, such that the Max-Heap provided by Rust // can be used as a Min-Heap fn cmp(&self, other: &Self) -> Ordering { - other.cost.cmp(&self.cost).then_with(|| self.index.cmp(&other.index)) + other + .cost + .cmp(&self.cost) + .then_with(|| self.index.cmp(&other.index)) } } @@ -190,11 +188,7 @@ impl GridGraph { let mut popcount = 0; - while let Some(DijkstraElement { - index, - cost, - }) = heap.pop() - { + while let Some(DijkstraElement { index, cost }) = heap.pop() { popcount += 1; if index == end.index { @@ -209,7 +203,7 @@ impl GridGraph { continue; }; - // println!("working on node {} with cost {}", index, cost); + //println!("working on node {} with cost {}", index, cost); let edge_start = self.edge_offsets[index as usize] as usize; let edge_end = self.edge_offsets[(index + 1) as usize] as usize; @@ -218,7 +212,7 @@ impl GridGraph { let new_cost = cost + edge.cost; if new_cost < distance[edge.neighbor as usize] { - // println!("found cheaper edge {:?} with cost {} than previous best {}", edge, new_cost, distance[edge.neighbor as usize]); + //println!("found cheaper edge {:?} with cost {} than previous best {}", edge, new_cost, distance[edge.neighbor as usize]); distance[edge.neighbor as usize] = new_cost; ancestor[edge.neighbor as usize] = Some(index); //println!("adding new element to heap"); @@ -227,7 +221,7 @@ impl GridGraph { cost: new_cost, }); } else { - // println!("edge {:?} is more expensive ({}) than the previous best {}", edge, new_cost, distance[edge.neighbor as usize]); + //println!("edge {:?} is more expensive ({}) than the previous best {}", edge, new_cost, distance[edge.neighbor as usize]); } } } @@ -305,7 +299,7 @@ impl GridGraph { let mut node_count: u32 = 0; let mut edge_count: u32 = 0; - let mut nodes: HashMap = HashMap::new(); + let mut node_map: HashMap = HashMap::new(); let mut edges: HashMap> = HashMap::new(); enum ParserState { @@ -316,6 +310,7 @@ impl GridGraph { Done, } + #[derive(Debug)] struct TemporaryGraphEdge { src: u32, dst: u32, @@ -388,25 +383,46 @@ impl GridGraph { match state { ParserState::NodeCount => { total_node_count = parse_int(line)?; + println!("found node count: {}", total_node_count); state = ParserState::EdgeCount {}; } ParserState::EdgeCount => { total_edge_count = parse_int(line)?; + println!("found edge count: {}", total_edge_count); state = ParserState::Nodes {}; } ParserState::Nodes => { - let node = parse_node(line)?; - nodes.entry(node.index).or_insert(node); + let mut node = parse_node(line)?; + // println!("parsed node: {:?}", node); node_count += 1; + + let new_index = gridgraph.nodes.len() as u32; + + node_map.insert(node.index, new_index); + node.index = new_index; + + gridgraph.nodes.push(node); + if node_count == total_node_count { + println!("done parsing nodes: {} nodes parsed", node_count); state = ParserState::Edges {}; } } ParserState::Edges => { - let edge = parse_edge(line)?; - edges.entry(edge.src).or_default().push(edge); + let mut edge = parse_edge(line)?; + // println!("parsed edge: {:?}", edge); edge_count += 1; + + let src = edge.src; + let dst = edge.dst; + + edge.src = node_map[&src]; + edge.dst = node_map[&dst]; + + edges.entry(edge.src).or_default().push(edge); + if edge_count == total_edge_count { + println!("done parsing edges: {} edges parsed", edge_count); state = ParserState::Done; } } @@ -423,31 +439,22 @@ impl GridGraph { return Err(FmiParsingError::WrongEdgeAmount); } - // add the nodes to the gridgraph - for (_, mut item) in nodes.iter_mut() { - item.index = gridgraph.nodes.len() as u32; - gridgraph.nodes.push(item.clone()); - } + // println!("{:?}", gridgraph); // add the edges gridgraph.edge_offsets.push(0); - for index in nodes.keys() { - for edge in edges.entry(*index).or_default() { - if !nodes.contains_key(&edge.dst) { - println!( - "An edge refers to the non-existing destination node {} skipping.", - edge.dst - ); - continue; - } - let dst_index = nodes[&edge.dst].index; + for index in 0..gridgraph.nodes.len() { + //println!("working on the edges for node {}", index); + for edge in edges.entry(index as u32).or_default() { + //println!("working on edge {:?}", edge); gridgraph.edges.push(GraphEdge { cost: edge.cost, - neighbor: dst_index, + neighbor: edge.dst, }); } gridgraph.edge_offsets.push(gridgraph.edges.len()); } + // println!("{:?}", gridgraph); gridgraph.lookup_grid = LookupGrid::new(100, 100, &gridgraph.nodes); @@ -485,7 +492,6 @@ impl GridGraph { lon_resolution: usize, polygons: Option<&PolygonSet>, ) -> Box { - #[derive(Debug)] struct TemporaryGraphNode { final_index: u32, @@ -518,7 +524,11 @@ impl GridGraph { Some(self.lon_index + (self.lat_index - 1) * lon_resolution) } - pub fn top_neighbor_index(&self, lat_resolution: usize, lon_resolution: usize) -> Option { + pub fn top_neighbor_index( + &self, + lat_resolution: usize, + lon_resolution: usize, + ) -> Option { if self.lat_index >= lat_resolution - 1 { return None; }; @@ -572,7 +582,6 @@ impl GridGraph { // add all edges to the final graph for node in temp_nodes.iter() { - println!("working on edges for node {:?}", node); if !node.used { continue;