fixed the broken FMI file parser

This commit is contained in:
Johannes Erwerle 2022-09-13 20:41:07 +02:00
parent 020ef5536f
commit 7d657b7222
6 changed files with 91 additions and 46 deletions

25
grids/grid_3x3.fmi Normal file
View file

@ -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

1
routes/10x10_1.json Normal file
View file

@ -0,0 +1 @@
[{"source":51,"destination":11}]

1
routes/3x3_1.json Normal file
View file

@ -0,0 +1 @@
[{"source":2,"destination":5}]

View file

@ -15,6 +15,15 @@ struct Args {
/// the output file to write the grid to /// the output file to write the grid to
#[clap(short, long)] #[clap(short, long)]
output: String, output: String,
/// the latitude resolution
#[clap(short, long)]
lat: usize,
/// the longitude resolution
#[clap(short, long)]
lon: usize,
} }
fn main() { fn main() {
@ -47,7 +56,7 @@ fn main() {
println!("{:?}", coasts.polygons[0].bbox); 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); // let grid = GridGraph::generate_regular_grid(3, 4, None);
match grid.write_fmi_file(output) { match grid.write_fmi_file(output) {

View file

@ -93,7 +93,7 @@ fn main() {
let source = astar.graph.nodes[query.source]; let source = astar.graph.nodes[query.source];
let destination = astar.graph.nodes[query.destination]; 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(); let elapsed = start.elapsed();
@ -109,13 +109,13 @@ fn main() {
let start = Instant::now(); let start = Instant::now();
for query in targets.iter() { for query in targets.iter() {
println!("working on {:?}", query); // println!("working on {:?}", query);
let source = astar.graph.nodes[query.source]; let source = astar.graph.nodes[query.source];
let destination = astar.graph.nodes[query.destination]; let destination = astar.graph.nodes[query.destination];
let result = astar.graph.shortest_path(&source, &destination); let result = astar.graph.shortest_path(&source, &destination);
println!("{}", result.unwrap().to_geojson()); //println!("{}", result.unwrap().to_geojson());
} }
let elapsed = start.elapsed(); let elapsed = start.elapsed();

View file

@ -1,16 +1,16 @@
use crate::coordinates::{DegreeCoordinate, RadianCoordinate}; use crate::coordinates::{DegreeCoordinate, RadianCoordinate};
use crate::polygonset::PolygonSet; use crate::polygonset::PolygonSet;
use crate::utils::EARTH_RADIUS;
use geojson::{Feature, FeatureCollection, Geometry, Position, Value}; use geojson::{Feature, FeatureCollection, Geometry, Position, Value};
use rand::seq::SliceRandom;
use serde::ser::{SerializeStruct, Serializer}; use serde::ser::{SerializeStruct, Serializer};
use serde::{Deserialize, Serialize};
use std::cmp::Ordering; use std::cmp::Ordering;
use std::collections::{BinaryHeap, HashMap}; use std::collections::{BinaryHeap, HashMap};
use std::f64::consts::{FRAC_PI_2, PI, TAU}; use std::f64::consts::{FRAC_PI_2, PI, TAU};
use std::fs::File; use std::fs::File;
use std::io::{BufRead, BufReader, Write}; use std::io::{BufRead, BufReader, Write};
use std::vec::Vec; use std::vec::Vec;
use crate::utils::EARTH_RADIUS;
use rand::seq::SliceRandom;
use serde::{Serialize, Deserialize};
/// Type for all edge costs /// Type for all edge costs
/// Allows for easy adjustments for bigger/smaller number types if that is /// Allows for easy adjustments for bigger/smaller number types if that is
@ -134,8 +134,6 @@ impl Route {
} }
impl GridGraph { impl GridGraph {
/// selects a single random graph node. /// selects a single random graph node.
pub fn get_random_node(&self) -> Option<&GraphNode> { pub fn get_random_node(&self) -> Option<&GraphNode> {
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
@ -143,14 +141,11 @@ impl GridGraph {
self.nodes.choose(&mut rng) self.nodes.choose(&mut rng)
} }
/// selects up to `amount` random but distinct nodes from the graph. /// 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(); let mut rng = rand::thread_rng();
self.nodes.choose_multiple(&mut rng, amount).collect() self.nodes.choose_multiple(&mut rng, amount).collect()
} }
/// calculates the shortest path from the start node to the end node. /// 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 // inverted cmp function, such that the Max-Heap provided by Rust
// can be used as a Min-Heap // can be used as a Min-Heap
fn cmp(&self, other: &Self) -> Ordering { 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; let mut popcount = 0;
while let Some(DijkstraElement { while let Some(DijkstraElement { index, cost }) = heap.pop() {
index,
cost,
}) = heap.pop()
{
popcount += 1; popcount += 1;
if index == end.index { if index == end.index {
@ -305,7 +299,7 @@ impl GridGraph {
let mut node_count: u32 = 0; let mut node_count: u32 = 0;
let mut edge_count: u32 = 0; let mut edge_count: u32 = 0;
let mut nodes: HashMap<u32, GraphNode> = HashMap::new(); let mut node_map: HashMap<u32, u32> = HashMap::new();
let mut edges: HashMap<u32, Vec<TemporaryGraphEdge>> = HashMap::new(); let mut edges: HashMap<u32, Vec<TemporaryGraphEdge>> = HashMap::new();
enum ParserState { enum ParserState {
@ -316,6 +310,7 @@ impl GridGraph {
Done, Done,
} }
#[derive(Debug)]
struct TemporaryGraphEdge { struct TemporaryGraphEdge {
src: u32, src: u32,
dst: u32, dst: u32,
@ -388,25 +383,46 @@ impl GridGraph {
match state { match state {
ParserState::NodeCount => { ParserState::NodeCount => {
total_node_count = parse_int(line)?; total_node_count = parse_int(line)?;
println!("found node count: {}", total_node_count);
state = ParserState::EdgeCount {}; state = ParserState::EdgeCount {};
} }
ParserState::EdgeCount => { ParserState::EdgeCount => {
total_edge_count = parse_int(line)?; total_edge_count = parse_int(line)?;
println!("found edge count: {}", total_edge_count);
state = ParserState::Nodes {}; state = ParserState::Nodes {};
} }
ParserState::Nodes => { ParserState::Nodes => {
let node = parse_node(line)?; let mut node = parse_node(line)?;
nodes.entry(node.index).or_insert(node); // println!("parsed node: {:?}", node);
node_count += 1; 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 { if node_count == total_node_count {
println!("done parsing nodes: {} nodes parsed", node_count);
state = ParserState::Edges {}; state = ParserState::Edges {};
} }
} }
ParserState::Edges => { ParserState::Edges => {
let edge = parse_edge(line)?; let mut edge = parse_edge(line)?;
edges.entry(edge.src).or_default().push(edge); // println!("parsed edge: {:?}", edge);
edge_count += 1; 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 { if edge_count == total_edge_count {
println!("done parsing edges: {} edges parsed", edge_count);
state = ParserState::Done; state = ParserState::Done;
} }
} }
@ -423,31 +439,22 @@ impl GridGraph {
return Err(FmiParsingError::WrongEdgeAmount); return Err(FmiParsingError::WrongEdgeAmount);
} }
// add the nodes to the gridgraph // println!("{:?}", gridgraph);
for (_, mut item) in nodes.iter_mut() {
item.index = gridgraph.nodes.len() as u32;
gridgraph.nodes.push(item.clone());
}
// add the edges // add the edges
gridgraph.edge_offsets.push(0); gridgraph.edge_offsets.push(0);
for index in nodes.keys() { for index in 0..gridgraph.nodes.len() {
for edge in edges.entry(*index).or_default() { //println!("working on the edges for node {}", index);
if !nodes.contains_key(&edge.dst) { for edge in edges.entry(index as u32).or_default() {
println!( //println!("working on edge {:?}", edge);
"An edge refers to the non-existing destination node {} skipping.",
edge.dst
);
continue;
}
let dst_index = nodes[&edge.dst].index;
gridgraph.edges.push(GraphEdge { gridgraph.edges.push(GraphEdge {
cost: edge.cost, cost: edge.cost,
neighbor: dst_index, neighbor: edge.dst,
}); });
} }
gridgraph.edge_offsets.push(gridgraph.edges.len()); gridgraph.edge_offsets.push(gridgraph.edges.len());
} }
// println!("{:?}", gridgraph);
gridgraph.lookup_grid = LookupGrid::new(100, 100, &gridgraph.nodes); gridgraph.lookup_grid = LookupGrid::new(100, 100, &gridgraph.nodes);
@ -485,7 +492,6 @@ impl GridGraph {
lon_resolution: usize, lon_resolution: usize,
polygons: Option<&PolygonSet>, polygons: Option<&PolygonSet>,
) -> Box<GridGraph> { ) -> Box<GridGraph> {
#[derive(Debug)] #[derive(Debug)]
struct TemporaryGraphNode { struct TemporaryGraphNode {
final_index: u32, final_index: u32,
@ -518,7 +524,11 @@ impl GridGraph {
Some(self.lon_index + (self.lat_index - 1) * lon_resolution) Some(self.lon_index + (self.lat_index - 1) * lon_resolution)
} }
pub fn top_neighbor_index(&self, lat_resolution: usize, lon_resolution: usize) -> Option<usize> { pub fn top_neighbor_index(
&self,
lat_resolution: usize,
lon_resolution: usize,
) -> Option<usize> {
if self.lat_index >= lat_resolution - 1 { if self.lat_index >= lat_resolution - 1 {
return None; return None;
}; };
@ -572,7 +582,6 @@ impl GridGraph {
// add all edges to the final graph // add all edges to the final graph
for node in temp_nodes.iter() { for node in temp_nodes.iter() {
println!("working on edges for node {:?}", node); println!("working on edges for node {:?}", node);
if !node.used { if !node.used {
continue; continue;