grid_tree/lib.rs
1//! [](https://crates.io/crates/grid-tree)
2//! [](https://docs.rs/grid-tree)
3//!
4//! Pixel quadtrees and voxel octrees.
5//!
6//! Store any type in an [`OctreeI32`](crate::OctreeI32), [`OctreeU32`](crate::OctreeU32), [`QuadtreeI32`](crate::QuadtreeI32),
7//! or [`QuadtreeU32`](crate::QuadtreeU32), all of which are specific instances of the generic [`Tree`](crate::Tree). A
8//! [`Tree`](crate::Tree) represents a map from `(Level, Integer Coordinates)` to `T`. Thus it is useful for storing pixel or
9//! voxel data with level-of-detail. The tree also requires that if a node slot is occupied (has data), then all ancestor slots
10//! are also filled.
11//!
12//! # Design Advantages
13//!
14//! - Since a [`Tree`](crate::Tree) has its own internal allocators, any pointers are completely local to the data structure. In
15//! principle, this makes it easy to clone the tree for e.g. uploading to a GPU (although we haven't tried it for ourselves).
16//! - The level 0 allocator does not store pointers, only values. Pointer overhead at higher levels can be amortized using
17//! chunked data, i.e. `[T; CHUNK_SIZE]`. The alternative "pointerless" octrees take up less memory, but are also more complex
18//! to edit and traverse.
19//! - By using a hash map of root nodes, the addressable space is not limited by the height of the tree, and it is not necessary
20//! to "translate" the octree as it follows a focal point.
21//! - By having a very simple data layout, access using a [`NodePtr`](crate::NodePtr) is simply an array lookup.
22//! - The [`NodeEntry`](crate::NodeEntry) and `Tree::child_entry` APIs allow for very simple code that fills entire trees with a
23//! single visitor closure.
24//! - By implementing [`VectorKey`](crate::VectorKey) for a custom key type, the addressable range can be extended to
25//! coordinates of arbitrary precision.
26//!
27//! # Performance
28//!
29//! This structure is optimized for iteration speed and spatial queries that benefit from a bounding volume hierarchy (like
30//! raycasting). Finding a single node by [`NodeKey`](crate::NodeKey) starting from the root should be minimized as much as
31//! possible, so you might find it useful to cache [`NodePtr`](crate::NodePtr)s or amortize the search with a full tree
32//! traversal. Memory usage is decent given the simplicity of the implementation, and the pointer overhead is easily amortized
33//! by using dense chunk values.
34//!
35//! - random access with [`NodeKey`](crate::NodeKey): O(depth)
36//! - random access with [`NodePtr`](crate::NodePtr): O(1)
37//! - iteration: O(nodes)
38//! - memory usage per node:
39//! - **level 0**: `size_of::<T>()` bytes
40//! - **level N > 0**: `size_of::<T>() + CHILDREN * 4` bytes
41//! - *where* `CHILDREN=4` for a quadtree and `CHILDREN=8` for an octree
42
43mod allocator;
44mod shape;
45mod tree;
46mod vector_key;
47
48pub use allocator::{AllocPtr, EMPTY_ALLOC_PTR};
49pub use shape::*;
50pub use tree::*;
51pub use vector_key::*;
52
53#[cfg(feature = "glam")]
54mod impl_glam;
55
56#[cfg(feature = "glam")]
57pub use impl_glam::*;
58
59#[cfg(feature = "glam")]
60pub use glam;
61
62/// A "level of detail" in a [`Tree`].
63pub type Level = u8;
64
65/// A linear index of a node relative to its parent.
66pub type ChildIndex = u8;
67
68use ahash::AHashMap;
69
70type SmallKeyHashMap<K, V> = AHashMap<K, V>;