fixed the broken FMI file parser
This commit is contained in:
parent
020ef5536f
commit
7d657b7222
6 changed files with 91 additions and 46 deletions
25
grids/grid_3x3.fmi
Normal file
25
grids/grid_3x3.fmi
Normal 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
1
routes/10x10_1.json
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
[{"source":51,"destination":11}]
|
||||||
1
routes/3x3_1.json
Normal file
1
routes/3x3_1.json
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
[{"source":2,"destination":5}]
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue