diff --git a/README.md b/README.md index 803f6c7..6f9f807 100644 --- a/README.md +++ b/README.md @@ -41,4 +41,22 @@ This might be a bit slow, alternatively, you can use `cargo run --release`. `backend-rust/download_data.sh` will download some data for the digital evelation model (DEM). Change `backend-rust/download_data.sh` according to your needs if you do not want to download all the data. -There is also an older (and slower) python backend in the `backend` folder. \ No newline at end of file +There is also an older (and slower) python backend in the `backend` folder. + +## Performance testing + +You can run performance tests using +``` +$ cargo bench +``` + +A flamegraph can be generated by adding the following to `Cargo.toml`: +``` +[profile.release] +#debug = 1 +``` +and then running +``` +$ kernel.perf_event_paranoid = -1 #Only needed once to enable event counting for flamegraph +$ cargo flamegraph --bench search_benchmark -- --bench +``` \ No newline at end of file diff --git a/backend-rust/src/pqueue.rs b/backend-rust/src/pqueue.rs index ebb0f87..11b5cc5 100644 --- a/backend-rust/src/pqueue.rs +++ b/backend-rust/src/pqueue.rs @@ -86,6 +86,13 @@ impl> PriorityQueue { positions: map, } } + + pub fn new_with_map_and_capacity(map: MapType, capacity: usize) -> Self { + Self { + heap: Vec::with_capacity(capacity), + positions: map, + } + } } impl> diff --git a/backend-rust/src/search.rs b/backend-rust/src/search.rs index c70547e..a438701 100644 --- a/backend-rust/src/search.rs +++ b/backend-rust/src/search.rs @@ -9,6 +9,7 @@ use ndarray::{linspace, s}; use crate::{ height_data::{get_height_at_point, get_height_data_around_point, HeightGrid}, + line::Line, pqueue::{MapLike, PriorityQueue}, }; @@ -245,18 +246,19 @@ impl SearchConfig { } pub fn get_neighbor_indices(ix: GridIx, height_grid: &HeightGrid) -> Vec { - let mut result = Vec::new(); - - let x = ix.0 as i32; - let y = ix.1 as i32; - for (a, b) in vec![(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)] { - if a >= 0 - && a < (height_grid.heights.shape()[0]) as i32 - && b >= 0 - && b < (height_grid.heights.shape()[1]) as i32 - { - result.push((a as GridIxType, b as GridIxType)); - } + let mut result = Vec::with_capacity(4); + + if ix.0 > 0 { + result.push((ix.0 - 1, ix.1)); + } + if ix.1 > 0 { + result.push((ix.0, ix.1 - 1)); + } + if ix.0 < (height_grid.heights.shape()[0] - 1) as GridIxType { + result.push((ix.0 + 1, ix.1)); + } + if ix.1 < (height_grid.heights.shape()[1] - 1) as GridIxType { + result.push((ix.0, ix.1 + 1)); } return result; @@ -667,6 +669,47 @@ pub fn f32_usize(x: f32) -> usize { usize::from(x as u16) } +pub fn is_line_intersecting_smart(to: &Node, ix: GridIx, config: &SearchConfig) -> bool { + let effective_glide = get_effective_glide_ratio_from_to(config, ix, to.ix); + if f32::is_infinite(effective_glide.glide_ratio) { + return true; + } + + let length = l2_distance(to.ix, ix); + + let grid_indices = Line::new((to.ix.0 as i16, to.ix.1 as i16), (ix.0 as i16, ix.1 as i16)); + + let distance = length * config.grid.cell_size; + let height_loss = distance * effective_glide.glide_ratio; + let final_height = to.height - height_loss; + + let mut real_height = if grid_indices.iterator_reversed() { + final_height + } else { + to.height + }; + let height_step = if grid_indices.iterator_reversed() { + height_loss / (grid_indices.num_pixels() - 1) as f32 + } else { + -height_loss / (grid_indices.num_pixels() - 1) as f32 + }; + + if config.safety_margin == 0.0 || to.distance + distance <= config.start_distance { + for (x_i, y_i) in grid_indices.iter() { + if real_height < config.grid.heights[(x_i as usize, y_i as usize)] as f32 { + return true; + } + real_height += height_step; + } + } else if to.distance < config.start_distance && to.distance + distance > config.start_distance + { + // TODO + } else { + // TODO + } + return false; +} + pub fn is_line_intersecting(to: &Node, ix: GridIx, config: &SearchConfig) -> bool { let effective_glide = get_effective_glide_ratio_from_to(config, ix, to.ix); if f32::is_infinite(effective_glide.glide_ratio) { @@ -746,6 +789,7 @@ pub fn reindex(explored: Explored, grid: &HeightGrid) -> (Explored, HeightGrid) let mut lat_max = GridIxType::MIN; let mut lon_min = GridIxType::MAX; let mut lon_max = GridIxType::MIN; + for node in explored.values.iter() { if node.is_some() { let n = node.as_ref().unwrap();