Skip to content

Commit

Permalink
rust: add Quadtree type to manipulate a set of keys
Browse files Browse the repository at this point in the history
Using the name Quadtree, despite not being a real implementation of it, to
match the mod and because we don't need a specific implementation of it
yet or any parsing performance specificaly

This could anyway be a good thing to bring a real tree implementation in
the future

Signed-off-by: Nicolas Buffon <nicolas.buffon@orange.com>
  • Loading branch information
nbuffon committed Jan 8, 2024
1 parent ba3a171 commit 861d7e4
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 0 deletions.
1 change: 1 addition & 0 deletions rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ thiserror = "1.0"

[dev-dependencies]
criterion = "0.5"
lazy_static = "1.4"

[[bench]]
name = "position"
Expand Down
111 changes: 111 additions & 0 deletions rust/src/mobility/quadtree.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::mobility::quadtree::quadkey::Quadkey;
use std::f64::consts::PI;

pub mod parse_error;
Expand All @@ -13,6 +14,16 @@ const MAX_LONGITUDE: f64 = 180.;
/// to represent a region that is at most 1m×1m in size
const DEFAULT_DEPTH: u16 = 26;

/// Convenience struct to hold a list of quadkeys
///
/// This is not a real tree representation but just a set of root-to-leaf branches
/// It might be interesting to look for en existing implementation of such a tree or to create one
pub type Quadtree = Vec<Quadkey>;

pub fn contains(quadtree: &Quadtree, quadkey: &Quadkey) -> bool {
quadtree.iter().any(|qk| quadkey <= qk)
}

fn coordinates_to_quadkey(latitude: f64, longitude: f64, depth: u16) -> String {
tile_xy_to_quadkey(
pixel_xy_to_tile_xy(coordinates_to_pixel_xy(latitude, longitude, depth)),
Expand Down Expand Up @@ -94,6 +105,11 @@ fn tile_xy_to_quadkey(tile: TileXY, level_of_detail: u16) -> String {
#[cfg(test)]
mod tests {
use crate::mobility::quadtree;
use crate::mobility::quadtree::quadkey::Quadkey;
use crate::mobility::quadtree::{contains, Quadtree};
use std::str::FromStr;

use lazy_static::lazy_static;

fn position() -> (f64, f64) {
(48.6263556, 2.2492123)
Expand Down Expand Up @@ -133,4 +149,99 @@ mod tests {
quadtree::coordinates_to_quadkey(latitude, longitude, 24),
)
}

lazy_static! {
static ref SHORT_ROOT_TREE: Quadtree = vec![Quadkey::from_str("12020").unwrap()];
static ref DEEP_LEAVES_TREE: Quadtree = vec![
Quadkey::from_str("12020322313211").unwrap(),
Quadkey::from_str("12020322313213").unwrap(),
Quadkey::from_str("12020322313302").unwrap(),
Quadkey::from_str("12020322313230").unwrap(),
Quadkey::from_str("12020322313221").unwrap(),
Quadkey::from_str("12020322313222").unwrap(),
Quadkey::from_str("120203223133032").unwrap(),
Quadkey::from_str("120203223133030").unwrap(),
Quadkey::from_str("120203223133012").unwrap(),
Quadkey::from_str("120203223133003").unwrap(),
Quadkey::from_str("120203223133002").unwrap(),
Quadkey::from_str("120203223133000").unwrap(),
Quadkey::from_str("120203223132103").unwrap(),
Quadkey::from_str("120203223132121").unwrap(),
Quadkey::from_str("120203223132123").unwrap(),
Quadkey::from_str("120203223132310").unwrap(),
Quadkey::from_str("120203223132311").unwrap(),
Quadkey::from_str("120203223132122").unwrap(),
Quadkey::from_str("120203223132033").unwrap(),
Quadkey::from_str("120203223132032").unwrap(),
Quadkey::from_str("120203223132023").unwrap(),
Quadkey::from_str("120203223132201").unwrap(),
Quadkey::from_str("120203223132203").unwrap(),
Quadkey::from_str("120203223132202").unwrap(),
Quadkey::from_str("120203223123313").unwrap(),
Quadkey::from_str("120203223123331").unwrap(),
Quadkey::from_str("120203223123333").unwrap(),
Quadkey::from_str("120203223132230").unwrap(),
Quadkey::from_str("1202032231330103").unwrap(),
Quadkey::from_str("12020322313300133").unwrap(),
Quadkey::from_str("12020322313301022").unwrap(),
Quadkey::from_str("12020322313301023").unwrap(),
];
}

macro_rules! test_quadtree_contains {
($test_name:ident, $tree:expr, $key:expr) => {
#[test]
fn $test_name() {
let contained = contains(&$tree, &$key);

assert!(contained);
}
};
}
test_quadtree_contains!(
several_deep_leaves_quadtree_contains_exact_quadkey,
DEEP_LEAVES_TREE,
Quadkey::from_str("12020322313301023").unwrap()
);
test_quadtree_contains!(
several_deep_leaves_quadtree_contains_deeper_quadkey,
DEEP_LEAVES_TREE,
Quadkey::from_str("1202032231330102321").unwrap()
);
test_quadtree_contains!(
short_root_only_tree_contains_exact_key,
SHORT_ROOT_TREE,
Quadkey::from_str("12020").unwrap()
);
test_quadtree_contains!(
short_root_only_tree_contains_deeper_key,
SHORT_ROOT_TREE,
Quadkey::from_str("12020123").unwrap()
);

macro_rules! test_quadtree_does_not_contain {
($test_name:ident, $tree:expr, $key:expr) => {
#[test]
fn $test_name() {
let contained = contains(&$tree, &$key);

assert!(!contained);
}
};
}
test_quadtree_does_not_contain!(
quadtree_does_not_contain_shorter_quadkey,
DEEP_LEAVES_TREE,
Quadkey::from_str("12020322").unwrap()
);
test_quadtree_does_not_contain!(
quadtree_does_not_contain_same_depth_quadkey,
DEEP_LEAVES_TREE,
Quadkey::from_str("12020322313300130").unwrap()
);
test_quadtree_does_not_contain!(
quadtree_does_not_contain_same_deeper_quadkey,
DEEP_LEAVES_TREE,
Quadkey::from_str("02020322313300130").unwrap()
);
}

0 comments on commit 861d7e4

Please sign in to comment.