packed_spatial_index
A fast, packed static spatial index for 2D and 3D axis-aligned bounding
boxes (AABBs). It builds a packed Hilbert R-tree (in the style of
flatbush /
static_aabb2d_index) once, then
answers many queries: range / intersection search, nearest-neighbor (kNN)
from a point or a box, ray casts, and spatial joins. With the simd
feature the SoA indexes use AVX2 / AVX-512 intersection tests; indexes also
serialize to a stable byte format with zero-copy views (mmap-friendly).
use ;
let mut builder = new;
builder.add;
builder.add;
let index = builder.finish?;
let hits = index.search;
assert_eq!;
# Ok::
Installation
Requires Rust 1.89 or newer.
[]
= "0.5"
When to use it
Use this crate when your geometry is static or rebuilt in batches, you can key
results by insertion-order index into your own payload array, and you want a
compact in-memory (or mmap'd) index with reusable buffers for high query
throughput. It is not a dynamic R-tree — there are no insert/delete
operations after finish().
Queries at a glance
Every query exists on Index2D / Index3D, the simd-feature SimdIndex2D /
SimdIndex3D, and the zero-copy views. Range/ray results are item indices in
insertion order; result order is unspecified. See
docs.rs for full per-method docs.
| Query | Methods |
|---|---|
| Range / intersection | search, search_into, search_with, any, first, visit |
| Nearest neighbors (point) | neighbors, neighbors_within, neighbors_into, neighbors_with, visit_neighbors |
| Nearest neighbors (box) | neighbors_of_box, neighbors_of_box_within, neighbors_of_box_into, neighbors_of_box_with, visit_neighbors_of_box |
| Ray segment | raycast, raycast_into, raycast_with, raycast_closest, raycast_closest_with, visit_raycast |
| Spatial join | join, join_with, self_join, self_join_with |
| Extent / exact | extent, and search_exact / neighbors_exact on the f32 indexes |
# use ;
# let mut b = new;
# b.add;
# b.add;
# let index = b.finish?;
let overlaps = index.search; // range query
let nearest = index.neighbors; // kNN
let hit = index.raycast_closest;
assert_eq!;
assert_eq!;
assert_eq!;
# Ok::
Types at a glance
- Geometry:
Box2D,Box3D(inclusiveoverlaps/contains/contains_point/from_point),Point2D,Point3D,Ray2D,Ray3D. - Builders:
Index2DBuilder,Index3DBuilder—finish(scalar),finish_simd(SoA + SIMD),finish_simd_f32(compact f32 boxes). - Indexes:
Index2D/Index3D(scalar),SimdIndex2D/SimdIndex3D(SIMD),SimdIndex2DF32/SimdIndex3DF32(half-memory f32 boxes). - Views: zero-copy
Index2DView/Index3DView(and SIMD / f32 view variants) over serialized bytes. - Workspaces:
SearchWorkspace/NeighborWorkspacereuse buffers in loops. - Sorting / errors:
SortKey2D/SortKey3D(defaultHilbert),BoundsError,BuildError,LoadError.
Features
parallel(default) — adaptive rayon-based parallel builds.simd(default) — SoA indexes and SIMD search/raycast (wide+ AVX-512).f32-storage— compact f32-storage SIMD indexes (impliessimd).bench-internals— hidden support API for this crate's benchmarks.
Documentation
- Guide — recipes, choosing a query method, builder configuration, examples, WASM demo.
- Persistence — serialize / load / zero-copy views, and querying large or on-disk indexes via mmap.
- Performance — benchmarks vs
static_aabb2d_index, FlatGeobuf, and thebvhcrate. - Binary format — the
PSINDEXon-disk layout. - API reference — docs.rs/packed_spatial_index.
Limitations
- Static: rebuild when the dataset changes; no insert/delete.
- Results are item indices, not stored payloads; result order is unspecified.
f32-storageindexes store outward-rounded boxes — plain range search may return extra near-boundary hits; usesearch_exact/neighbors_exact(with your sourcef64boxes) for exact results, and preferf64indexes for exact queries with many hits.
Safety
The public API is safe Rust. Internally unsafe is confined to narrow, audited
paths: validated unaligned little-endian reads in the byte views, bulk
repr(C) byte copies during serialization on little-endian targets, and
runtime-feature-gated x86-64 SIMD (AVX-512) loads/prefetch. Loaded buffers are
validated before use, so malformed input returns LoadError rather than relying
on caller invariants.
Status
Major API changes are not planned, but remain possible before a 1.0 release.
AI usage note
AI assistance is part of my development process for this project. I guide the architecture, review generated output carefully, and take responsibility for the crate as published.
License
Licensed under the Apache License, Version 2.0.