diff --git a/Cargo.toml b/Cargo.toml index f7e8a78..9853cbc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,11 +4,12 @@ version = "0.1.0" authors = ["Jay Kickliter ", "Andrew Thompson "] categories = ["science", "data-structures"] edition = "2018" -exclude = ["/test/*"] +exclude = [".github/*", "/assets/*", "/test/*"] readme = "README.md" keywords = ["geo", "geography", "geospatial", "gis", "h3"] license = "MIT OR Apache-2.0" -repository = "https://github.com/jaykickliter/hexmap" +homepage = "https://github.com/jaykickliter/HexTree" +repository = "https://github.com/jaykickliter/HexTree" description = """ Location to value mapping. """ @@ -25,9 +26,9 @@ h3ron = { version = "0.15" } serde = { version = "1", optional = true, features = ["derive"] } [dev-dependencies] -byteorder = "*" +byteorder = "1" criterion = { version = "0.3", features = ["html_reports"] } -geo-types = "*" +geo-types = "0.7" [dev-dependencies.h3-lorawan-regions] git = "https://github.com/JayKickliter/h3-lorawan-regions.git" diff --git a/README.md b/README.md index f24b503..fe46191 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,45 @@ -# HexSet +[![CI](https://github.com/JayKickliter/HexTree/actions/workflows/rust.yml/badge.svg)](https://github.com/JayKickliter/HexTree/actions/workflows/rust.yml) [![Documentation](https://docs.rs/hextree/badge.svg)](https://docs.rs/hextree) -A HexSet is a data structure for efficient [point-in-polygon] testing -of geographic regions. +# HexTree -You, the user, create a set by inserting [H3 cells] into a -HexSet. Internally, HexSet decomposes cells into a tree of -resolution-0 cells at the root, branching through intermediate -resolutions until reaching the leaf cells you inserted. +hextree provides tree structures that represent geographic regions +with [H3 cell]s. -HexSet automatically coalesces: on insert, any complete intermediate -cell in the tree is turned into a leaf cell. "Complete" is defined as -having all possibly child cells. Coalescing a cell allows for -optimized search, as any child cell of the coalesced cell is known to -be contained in the set. +The primary structures are: -[point-in-polygon]: https://en.wikipedia.org/wiki/Point_in_polygon -[H3 cells]: https://h3geo.org/docs/core-library/h3Indexing +- **HexTreeMap**: an H3 cell-to-value map. +- **HexTreeSet**: an H3 cell set for hit-testing. + +You can think of `HexTreeMap` vs. `HexTreeSet` as [`HashMap`] vs. [`HashSet`]. + +## How is this different from `HashMap`? + +The key feature of a hextree is that its keys (H3 cells) are +hierarchical. For instance, if you previously inserted an entry for a +low-res hex, but later query for a higher-res child hex, the tree +returns the value for the lower res hex. Additionally, with +[compaction], trees can automatically coalesce adjacent high-res +hexagons into their parent hex. For very large regions, the compaction +process _can_ continue to lowest resolution cells (res-0), possibly +removing millions of redundant cells from the tree. For example, a set +of 4,795,661 res-7 cells representing North America coalesces [into a +42,383 element `HexTreeSet`][us915]. + +A hextree's internal structure exactly matches the semantics of an [H3 +cell]. The root of the tree has 122 resolution-0 nodes, followed by 15 +levels of 7-ary nodes. The level of an occupied node, or leaf node, is +the same as its corresponding H3 cell resolution. + +## Features + +* **`serde-support`**: support for serialization via [serde]. + +[`HashMap`]: https://doc.rust-lang.org/std/collections/struct.HashMap.html +[`HashSet`]: https://doc.rust-lang.org/std/collections/struct.HashSet.html +[H3 cell]: https://h3geo.org/docs/core-library/h3Indexing +[serde]: https://docs.rs/serde/latest/serde +[compaction]: crate::compaction +[us915]: https://www.google.com/maps/d/u/0/edit?mid=15wRzxmtmyzqf6fHU3yuW4hJAM9MoxLJs ## License diff --git a/benches/benches.rs b/benches/benches.rs index 66f60e2..df73a33 100644 --- a/benches/benches.rs +++ b/benches/benches.rs @@ -3,13 +3,13 @@ use geo_types::coord; use h3_lorawan_regions::{ compact::US915 as COMPACT_US915_INDICES, nocompact::US915 as PLAIN_US915_INDICES, }; -use hextree::{compaction::EqCompactor, h3ron::H3Cell, HexMap, HexSet}; +use hextree::{compaction::EqCompactor, h3ron::H3Cell, HexTreeMap, HexTreeSet}; use std::convert::TryFrom; -fn hexset_lookup(c: &mut Criterion) { - let mut group = c.benchmark_group("US915 HexSet lookup"); +fn set_lookup(c: &mut Criterion) { + let mut group = c.benchmark_group("US915 HexTreeSet lookup"); - let us915_hexset: HexSet = PLAIN_US915_INDICES + let us915_set: HexTreeSet = PLAIN_US915_INDICES .iter() .map(|&idx| H3Cell::try_from(idx).unwrap()) .collect(); @@ -26,23 +26,23 @@ fn hexset_lookup(c: &mut Criterion) { group.bench_with_input( BenchmarkId::new("Tarpon Spring", resolution), &tarpon_springs, - |b, &cell| b.iter(|| us915_hexset.contains(cell)), + |b, &cell| b.iter(|| us915_set.contains(cell)), ); group.bench_with_input( BenchmarkId::new("Gulf of Mexico", resolution), &gulf_of_mexico, - |b, &cell| b.iter(|| us915_hexset.contains(cell)), + |b, &cell| b.iter(|| us915_set.contains(cell)), ); group.bench_with_input(BenchmarkId::new("Paris", resolution), &paris, |b, &cell| { - b.iter(|| us915_hexset.contains(cell)) + b.iter(|| us915_set.contains(cell)) }); } } -fn hexset_construction(c: &mut Criterion) { - let mut group = c.benchmark_group("US915 HexSet construction"); +fn set_construction(c: &mut Criterion) { + let mut group = c.benchmark_group("US915 HexTreeSet construction"); let precompacted_us915_cells: Vec = COMPACT_US915_INDICES .iter() @@ -54,15 +54,15 @@ fn hexset_construction(c: &mut Criterion) { .collect(); group.bench_function("pre-compacted", |b| { - b.iter(|| precompacted_us915_cells.iter().collect::()) + b.iter(|| precompacted_us915_cells.iter().collect::()) }); group.bench_function("plain", |b| { - b.iter(|| plain_us915_cells.iter().collect::()) + b.iter(|| plain_us915_cells.iter().collect::()) }); } -fn hexmap_lookup(c: &mut Criterion) { +fn map_lookup(c: &mut Criterion) { #[derive(Clone, Copy, PartialEq, Eq, Debug)] #[allow(dead_code)] enum Region { @@ -70,10 +70,10 @@ fn hexmap_lookup(c: &mut Criterion) { US915, } - let mut group = c.benchmark_group("US915 HexMap lookup"); + let mut group = c.benchmark_group("US915 HexTreeMap lookup"); - let mut us915_hexmap = HexMap::with_compactor(EqCompactor); - us915_hexmap.extend( + let mut us915_map = HexTreeMap::with_compactor(EqCompactor); + us915_map.extend( PLAIN_US915_INDICES .iter() .map(|&idx| H3Cell::try_from(idx).unwrap()) @@ -92,22 +92,22 @@ fn hexmap_lookup(c: &mut Criterion) { group.bench_with_input( BenchmarkId::new("Tarpon Spring", resolution), &tarpon_springs, - |b, &cell| b.iter(|| us915_hexmap.get(cell)), + |b, &cell| b.iter(|| us915_map.get(cell)), ); group.bench_with_input( BenchmarkId::new("Gulf of Mexico", resolution), &gulf_of_mexico, - |b, &cell| b.iter(|| us915_hexmap.get(cell)), + |b, &cell| b.iter(|| us915_map.get(cell)), ); group.bench_with_input(BenchmarkId::new("Paris", resolution), &paris, |b, &cell| { - b.iter(|| us915_hexmap.get(cell)) + b.iter(|| us915_map.get(cell)) }); } } -fn hexmap_construction(c: &mut Criterion) { +fn map_construction(c: &mut Criterion) { // The value type for the map #[derive(Clone, Copy, PartialEq, Eq, Debug)] #[allow(dead_code)] @@ -116,7 +116,7 @@ fn hexmap_construction(c: &mut Criterion) { US915, } - let mut group = c.benchmark_group("US915 HexMap construction"); + let mut group = c.benchmark_group("US915 HexTreeMap construction"); let precompacted_us915_cells: Vec = COMPACT_US915_INDICES .iter() @@ -129,7 +129,7 @@ fn hexmap_construction(c: &mut Criterion) { group.bench_function("pre-compacted", |b| { b.iter(|| { - let mut map = HexMap::with_compactor(EqCompactor); + let mut map = HexTreeMap::with_compactor(EqCompactor); map.extend( precompacted_us915_cells .iter() @@ -142,7 +142,7 @@ fn hexmap_construction(c: &mut Criterion) { group.bench_function("plain", |b| { b.iter(|| { - let mut map = HexMap::with_compactor(EqCompactor); + let mut map = HexTreeMap::with_compactor(EqCompactor); map.extend( plain_us915_cells .iter() @@ -156,9 +156,9 @@ fn hexmap_construction(c: &mut Criterion) { criterion_group!( benches, - hexset_lookup, - hexmap_lookup, - hexset_construction, - hexmap_construction, + set_lookup, + map_lookup, + set_construction, + map_construction, ); criterion_main!(benches); diff --git a/src/entry.rs b/src/entry.rs index 5bba655..f490e8d 100644 --- a/src/entry.rs +++ b/src/entry.rs @@ -1,12 +1,12 @@ -//! `HexMap`'s Entry API. +//! `HexTreeMap`'s Entry API. -use crate::{compaction::Compactor, h3ron::H3Cell, HexMap}; +use crate::{compaction::Compactor, h3ron::H3Cell, HexTreeMap}; /// A view into a single entry in a map, which may either be vacant or /// occupied. /// -/// This enum is constructed from the [entry][HexMap::entry] method on -/// [HexMap][HexMap]. +/// This enum is constructed from the [entry][HexTreeMap::entry] +/// method on [HexTreeMap][HexTreeMap]. pub enum Entry<'a, V, C> { /// An occupied entry. Occupied(OccupiedEntry<'a, V>), @@ -14,18 +14,18 @@ pub enum Entry<'a, V, C> { Vacant(VacantEntry<'a, V, C>), } -/// A view into an occupied entry in a `HexMap`. It is part of the +/// A view into an occupied entry in a `HexTreeMap`. It is part of the /// [`Entry`] enum. pub struct OccupiedEntry<'a, V> { pub(crate) hex: H3Cell, pub(crate) value: &'a mut V, } -/// A view into a vacant entry in a `HexMap`. It is part of the +/// A view into a vacant entry in a `HexTreeMap`. It is part of the /// [`Entry`] enum. pub struct VacantEntry<'a, V, C> { pub(crate) hex: H3Cell, - pub(crate) map: &'a mut HexMap, + pub(crate) map: &'a mut HexTreeMap, } impl<'a, V, C> Entry<'a, V, C> @@ -38,9 +38,9 @@ where /// # Examples /// /// ``` - /// use hextree::{h3ron::{H3Cell, Index}, HexMap}; + /// use hextree::{h3ron::{H3Cell, Index}, HexTreeMap}; /// - /// let mut map = HexMap::new(); + /// let mut map = HexTreeMap::new(); /// let eiffel_tower_res12 = H3Cell::new(0x8c1fb46741ae9ff); /// /// map.entry(eiffel_tower_res12) @@ -73,9 +73,9 @@ where /// # Examples /// /// ``` - /// use hextree::{h3ron::{H3Cell, Index}, HexMap}; + /// use hextree::{h3ron::{H3Cell, Index}, HexTreeMap}; /// - /// let mut map = HexMap::new(); + /// let mut map = HexTreeMap::new(); /// let eiffel_tower_res12 = H3Cell::new(0x8c1fb46741ae9ff); /// /// map.entry(eiffel_tower_res12) @@ -100,9 +100,9 @@ where /// # Examples /// /// ``` - /// use hextree::{h3ron::{H3Cell, Index}, HexMap}; + /// use hextree::{h3ron::{H3Cell, Index}, HexTreeMap}; /// - /// let mut map = HexMap::new(); + /// let mut map = HexTreeMap::new(); /// let eiffel_tower_res12 = H3Cell::new(0x8c1fb46741ae9ff); /// /// map.entry(eiffel_tower_res12) @@ -136,9 +136,9 @@ where /// # Examples /// /// ``` - /// use hextree::{h3ron::{H3Cell, Index}, HexMap}; + /// use hextree::{h3ron::{H3Cell, Index}, HexTreeMap}; /// - /// let mut map: HexMap> = HexMap::new(); + /// let mut map: HexTreeMap> = HexTreeMap::new(); /// let eiffel_tower_res12 = H3Cell::new(0x8c1fb46741ae9ff); /// /// map.entry(eiffel_tower_res12).or_default(); diff --git a/src/hexmap.rs b/src/hex_tree_map.rs similarity index 82% rename from src/hexmap.rs rename to src/hex_tree_map.rs index dd44f46..8288fc4 100644 --- a/src/hexmap.rs +++ b/src/hex_tree_map.rs @@ -1,4 +1,4 @@ -//! A HexMap is a structure for mapping geographical regions to values. +//! A HexTreeMap is a structure for mapping geographical regions to values. pub use crate::entry::{Entry, OccupiedEntry, VacantEntry}; use crate::{ @@ -9,7 +9,8 @@ use crate::{ }; use std::{cmp::PartialEq, iter::FromIterator}; -/// A HexMap is a structure for mapping geographical regions to values. +/// A HexTreeMap is a structure for mapping geographical regions to +/// values. /// /// /// [serde]: https://docs.rs/serde/latest/serde/ @@ -20,14 +21,14 @@ use std::{cmp::PartialEq, iter::FromIterator}; /// /// ---- /// -/// Let's create a HexMap for Monaco as visualized in the map +/// Let's create a HexTreeMap for Monaco as visualized in the map /// /// ``` /// # use hextree::h3ron::Error; /// # /// # fn main() -> Result<(), Error> { /// use geo_types::coord; -/// use hextree::{h3ron::H3Cell, compaction::EqCompactor, HexMap}; +/// use hextree::{h3ron::H3Cell, compaction::EqCompactor, HexTreeMap}; /// # /// # use byteorder::{LittleEndian as LE, ReadBytesExt}; /// # use hextree::h3ron::{Index, FromH3Index}; @@ -45,7 +46,7 @@ use std::{cmp::PartialEq, iter::FromIterator}; /// /// // Construct map with a compactor that automatically combines /// // cells with the same save value. -/// let mut monaco = HexMap::with_compactor(EqCompactor); +/// let mut monaco = HexTreeMap::with_compactor(EqCompactor); /// /// // Now extend the map with cells and a region value. /// monaco.extend(cells.iter().copied().zip(std::iter::repeat(Region::Monaco))); @@ -66,15 +67,16 @@ use std::{cmp::PartialEq, iter::FromIterator}; feature = "serde-support", derive(serde::Serialize, serde::Deserialize) )] -pub struct HexMap { +pub struct HexTreeMap { /// All h3 0 base cell indices in the tree nodes: Box<[Option>]>, /// User-provided compator. Defaults to the null compactor. compactor: C, } -impl HexMap { - /// Constructs a new, empty `HexMap` with the no-op `NullCompactor`. +impl HexTreeMap { + /// Constructs a new, empty `HexTreeMap` with the no-op + /// `NullCompactor`. /// /// Incurs a single heap allocation to store all 122 resolution-0 /// H3 cells. @@ -89,7 +91,7 @@ impl HexMap { } } -impl> HexMap { +impl> HexTreeMap { /// Adds a hexagon/value pair to the set. pub fn insert(&mut self, hex: H3Cell, value: V) { let base_cell = base(hex); @@ -105,8 +107,9 @@ impl> HexMap { } } -impl HexMap { - /// Constructs a new, empty `HexMap` with the provided [compactor][crate::compaction]. +impl HexTreeMap { + /// Constructs a new, empty `HexTreeMap` with the provided + /// [compactor][crate::compaction]. /// /// Incurs a single heap allocation to store all 122 resolution-0 /// H3 cells. @@ -120,13 +123,14 @@ impl HexMap { } } - /// Replace the current compactor with the new one, consuming `self`. + /// Replace the current compactor with the new one, consuming + /// `self`. /// /// This method is useful if you want to use one compaction /// strategy for creating an initial, then another one for updates /// later. - pub fn replace_compactor(self, new_compactor: NewC) -> HexMap { - HexMap { + pub fn replace_compactor(self, new_compactor: NewC) -> HexTreeMap { + HexTreeMap { nodes: self.nodes, compactor: new_compactor, } @@ -207,18 +211,18 @@ impl HexMap { } } -impl Default for HexMap { +impl Default for HexTreeMap { fn default() -> Self { - HexMap::new() + HexTreeMap::new() } } -impl FromIterator<(H3Cell, V)> for HexMap { +impl FromIterator<(H3Cell, V)> for HexTreeMap { fn from_iter(iter: I) -> Self where I: IntoIterator, { - let mut map = HexMap::new(); + let mut map = HexTreeMap::new(); for (cell, value) in iter { map.insert(cell, value); } @@ -226,12 +230,12 @@ impl FromIterator<(H3Cell, V)> for HexMap { } } -impl<'a, V: Copy + 'a> FromIterator<(&'a H3Cell, &'a V)> for HexMap { +impl<'a, V: Copy + 'a> FromIterator<(&'a H3Cell, &'a V)> for HexTreeMap { fn from_iter(iter: I) -> Self where I: IntoIterator, { - let mut map = HexMap::new(); + let mut map = HexTreeMap::new(); for (cell, value) in iter { map.insert(*cell, *value); } @@ -239,7 +243,7 @@ impl<'a, V: Copy + 'a> FromIterator<(&'a H3Cell, &'a V)> for HexMap> Extend<(H3Cell, V)> for HexMap { +impl> Extend<(H3Cell, V)> for HexTreeMap { fn extend>(&mut self, iter: I) { for (cell, val) in iter { self.insert(cell, val) @@ -247,7 +251,7 @@ impl> Extend<(H3Cell, V)> for HexMap { } } -impl<'a, V: Copy + 'a, C: Compactor> Extend<(&'a H3Cell, &'a V)> for HexMap { +impl<'a, V: Copy + 'a, C: Compactor> Extend<(&'a H3Cell, &'a V)> for HexTreeMap { fn extend>(&mut self, iter: I) { for (cell, val) in iter { self.insert(*cell, *val) @@ -255,7 +259,7 @@ impl<'a, V: Copy + 'a, C: Compactor> Extend<(&'a H3Cell, &'a V)> for HexMap std::ops::Index for HexMap { +impl std::ops::Index for HexTreeMap { type Output = V; /// Returns a reference to the value corresponding to the supplied @@ -264,9 +268,9 @@ impl std::ops::Index for HexMap { /// # Examples /// /// ``` - /// use hextree::{h3ron::{H3Cell, Index}, HexMap}; + /// use hextree::{h3ron::{H3Cell, Index}, HexTreeMap}; /// - /// let mut map = HexMap::new(); + /// let mut map = HexTreeMap::new(); /// let eiffel_tower_res12 = H3Cell::new(0x8c1fb46741ae9ff); /// /// map.insert(eiffel_tower_res12, "France"); @@ -275,13 +279,13 @@ impl std::ops::Index for HexMap { /// /// # Panics /// - /// Panics if the cell is not present in the `HexMap`. + /// Panics if the cell is not present in the `HexTreeMap`. fn index(&self, cell: H3Cell) -> &V { self.get(cell).expect("no entry found for cell") } } -impl std::ops::Index<&H3Cell> for HexMap { +impl std::ops::Index<&H3Cell> for HexTreeMap { type Output = V; /// Returns a reference to the value corresponding to the supplied @@ -290,9 +294,9 @@ impl std::ops::Index<&H3Cell> for HexMap { /// # Examples /// /// ``` - /// use hextree::{h3ron::{H3Cell, Index}, HexMap}; + /// use hextree::{h3ron::{H3Cell, Index}, HexTreeMap}; /// - /// let mut map = HexMap::new(); + /// let mut map = HexTreeMap::new(); /// let eiffel_tower_res12 = H3Cell::new(0x8c1fb46741ae9ff); /// /// map.insert(eiffel_tower_res12, "France"); @@ -301,22 +305,22 @@ impl std::ops::Index<&H3Cell> for HexMap { /// /// # Panics /// - /// Panics if the cell is not present in the `HexMap`. + /// Panics if the cell is not present in the `HexTreeMap`. fn index(&self, cell: &H3Cell) -> &V { self.get(*cell).expect("no entry found for cell") } } -impl std::ops::IndexMut for HexMap { +impl std::ops::IndexMut for HexTreeMap { /// Returns a reference to the value corresponding to the supplied /// key. /// /// # Examples /// /// ``` - /// use hextree::{h3ron::{H3Cell, Index}, HexMap}; + /// use hextree::{h3ron::{H3Cell, Index}, HexTreeMap}; /// - /// let mut map = HexMap::new(); + /// let mut map = HexTreeMap::new(); /// let eiffel_tower_res12 = H3Cell::new(0x8c1fb46741ae9ff); /// /// map.insert(eiffel_tower_res12, "France"); @@ -328,22 +332,22 @@ impl std::ops::IndexMut for HexMap { /// /// # Panics /// - /// Panics if the cell is not present in the `HexMap`. + /// Panics if the cell is not present in the `HexTreeMap`. fn index_mut(&mut self, cell: H3Cell) -> &mut V { self.get_mut(cell).expect("no entry found for cell") } } -impl std::ops::IndexMut<&H3Cell> for HexMap { +impl std::ops::IndexMut<&H3Cell> for HexTreeMap { /// Returns a reference to the value corresponding to the supplied /// key. /// /// # Examples /// /// ``` - /// use hextree::{h3ron::{H3Cell, Index}, HexMap}; + /// use hextree::{h3ron::{H3Cell, Index}, HexTreeMap}; /// - /// let mut map = HexMap::new(); + /// let mut map = HexTreeMap::new(); /// let eiffel_tower_res12 = H3Cell::new(0x8c1fb46741ae9ff); /// /// map.insert(eiffel_tower_res12, "France"); @@ -355,7 +359,7 @@ impl std::ops::IndexMut<&H3Cell> for HexMap { /// /// # Panics /// - /// Panics if the cell is not present in the `HexMap`. + /// Panics if the cell is not present in the `HexTreeMap`. fn index_mut(&mut self, cell: &H3Cell) -> &mut V { self.get_mut(*cell).expect("no entry found for cell") } diff --git a/src/hexset.rs b/src/hex_tree_set.rs similarity index 68% rename from src/hexset.rs rename to src/hex_tree_set.rs index d4cc679..5ac63c2 100644 --- a/src/hexset.rs +++ b/src/hex_tree_set.rs @@ -1,9 +1,9 @@ -use crate::{compaction::SetCompactor, h3ron::H3Cell, HexMap}; +use crate::{compaction::SetCompactor, h3ron::H3Cell, HexTreeMap}; use std::iter::FromIterator; -/// A HexSex is a structure for representing geographical regions and -/// efficiently testing performing hit-tests on that region. Or, in -/// other words: I have a region defined; does it contain this +/// A HexTreeSet is a structure for representing geographical regions +/// and efficiently testing performing hit-tests on that region. Or, +/// in other words: I have a region defined; does it contain this /// point on earth? /// /// @@ -13,14 +13,14 @@ use std::iter::FromIterator; /// /// ---- /// -/// Let's create a HexSet for Monaco as visualized in the map +/// Let's create a HexTreeSet for Monaco as visualized in the map /// /// ``` /// # use hextree::h3ron::Error; /// # /// # fn main() -> Result<(), Error> { /// use geo_types::coord; -/// use hextree::{h3ron::H3Cell, HexSet}; +/// use hextree::{h3ron::H3Cell, HexTreeSet}; /// # /// # use byteorder::{LittleEndian as LE, ReadBytesExt}; /// # use hextree::h3ron::FromH3Index; @@ -32,7 +32,7 @@ use std::iter::FromIterator; /// # } /// /// // `cells` is a slice of `H3Cell`s -/// let monaco: HexSet = cells.iter().collect(); +/// let monaco: HexTreeSet = cells.iter().collect(); /// /// // You can see in the map above that our set covers Point 1 (green /// // check) but not Point 2 (red x), let's test that. @@ -45,14 +45,14 @@ use std::iter::FromIterator; /// # Ok(()) /// # } /// ``` -pub type HexSet = HexMap<(), SetCompactor>; +pub type HexTreeSet = HexTreeMap<(), SetCompactor>; -impl FromIterator for HexSet { +impl FromIterator for HexTreeSet { fn from_iter(iter: I) -> Self where I: IntoIterator, { - let mut set = HexMap::with_compactor(SetCompactor); + let mut set = HexTreeMap::with_compactor(SetCompactor); for cell in iter { set.insert(cell, ()); } @@ -60,12 +60,12 @@ impl FromIterator for HexSet { } } -impl<'a> FromIterator<&'a H3Cell> for HexSet { +impl<'a> FromIterator<&'a H3Cell> for HexTreeSet { fn from_iter(iter: I) -> Self where I: IntoIterator, { - let mut set = HexMap::with_compactor(SetCompactor); + let mut set = HexTreeMap::with_compactor(SetCompactor); for cell in iter { set.insert(*cell, ()); } diff --git a/src/lib.rs b/src/lib.rs index fbdab35..ebdd599 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,10 +3,10 @@ //! hextree provides tree structures that represent geographic regions with H3 cells. //! //! The primary structures are: -//! - [`HexMap`][crate::HexMap]: an H3Cell-to-value map. -//! - [`HexSet`][crate::HexSet]: an H3Cell set for hit-testing. +//! - [`HexTreeMap`][crate::HexTreeMap]: an H3Cell-to-value map. +//! - [`HexTreeSet`][crate::HexTreeSet]: an H3Cell set for hit-testing. //! -//! You can think of `HexMap` vs. `HexSet` as [`HashMap`] vs. [`HashSet`]. +//! You can think of `HexTreeMap` vs. `HexTreeSet` as [`HashMap`] vs. [`HashSet`]. //! //! For the rest of the documentation, we will use hextree to refer to //! the general data structure. @@ -22,7 +22,7 @@ //! compaction process _can_ continue to lowest resolution cells //! (res-0), possibly removing millions of redundant cells from the //! tree. For example, a set of 4,795,661 res-7 cells representing -//! North America coalesces [into a 42,383 element `HexSet`][us915]. +//! North America coalesces [into a 42,383 element `HexTreeSet`][us915]. //! //! A hextree's internal structure exactly matches the semantics of an //! [H3 cell]. The root of the tree has 122 resolution-0 nodes, @@ -44,10 +44,10 @@ pub mod compaction; mod digits; mod entry; -pub mod hexmap; -mod hexset; +pub mod hex_tree_map; +mod hex_tree_set; mod node; -pub use crate::hexmap::HexMap; -pub use crate::hexset::HexSet; +pub use crate::hex_tree_map::HexTreeMap; +pub use crate::hex_tree_set::HexTreeSet; pub use h3ron; diff --git a/tests/tests.rs b/tests/tests.rs index 08a9af0..f19374a 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -3,7 +3,7 @@ use h3_lorawan_regions as regions; use hextree::{ compaction::EqCompactor, h3ron::{H3Cell, Index}, - HexMap, HexSet, + HexTreeMap, HexTreeSet, }; use std::convert::TryFrom; /// Perform a linear search of `region` for `target` cell. @@ -26,12 +26,12 @@ fn naive_contains(region: &[H3Cell], target: H3Cell) -> bool { false } -fn from_indicies(indicies: &[u64]) -> (HexSet, Vec) { +fn from_indicies(indicies: &[u64]) -> (HexTreeSet, Vec) { let cells: Vec = indicies .iter() .map(|&idx| H3Cell::try_from(idx).unwrap()) .collect(); - let set: HexSet = cells.iter().collect(); + let set: HexTreeSet = cells.iter().collect(); (set, cells) } @@ -57,7 +57,7 @@ fn all_up() { } #[test] -fn mono_hexmap() { +fn mono_map() { #[derive(Clone, Copy, PartialEq, Eq, Debug)] enum Region { EU868, @@ -70,7 +70,7 @@ fn mono_hexmap() { (US915, regions::nocompact::US915), ]; - let mut monomap = HexMap::with_compactor(EqCompactor); + let mut monomap = HexTreeMap::with_compactor(EqCompactor); for (name, cells) in regions.iter() { for cell in cells.iter() {