3D spatial zone engine — geofencing, octree hole-scanning, realtime sync, voxel pathfinding, and AV sensor fusion. One crate, every domain.
[dependencies]
plozone = { version = "0.1", features = ["full"] }use plozone::{
coord::EnuConverter, octree::OctreeNode,
store::ZoneStore, zone::{Zone, ZoneEntry},
scan::{run_scan, ScanMode},
};
// WGS84 origin in Ho Chi Minh City
let conv = EnuConverter::new(10.7626, 106.6601, 0.0);
let store = ZoneStore::from_entries(&[
ZoneEntry::new(1, Zone::Cylinder {
center: [10.7626, 106.6601], radius_m: 50.0,
z_min: 0.0, z_max: 20.0,
}),
], &conv);
// Is this point inside the zone?
let hits = store.query_geodetic(10.7626, 106.6601, 5.0, &conv);
assert_eq!(hits.as_slice(), &[1]);
// Scan for unsampled regions in the octree
let octree = OctreeNode::new([0.0; 3], 64.0);
let result = run_scan(&octree, &store, 1, &ScanMode::Coarse { depth: 4 });
println!("coverage: {:.1}%", result.coverage_pct);Every spatial project reinvents the same primitives. Plozone answers is this point inside a zone?, did the entity enter or leave?, and is this region fully scanned? across real-world geospatial, game maps, robotics, autonomous vehicles, and IoT — with one consistent API.
User Input (WGS84 / game / sensor) ──► CoordSystem
│
ZoneStore ◄── R-tree indexed ── Box<dyn ZoneShape>
│ │
├── query_enu < 1 µs point-in-zone
├── query_geodetic any lat/lon/alt
├── layer queries filtered by priority
└── top_priority tie-breaks on id
OctreeNode ── adaptive subdivision (max depth 17, ~4mm voxels)
│
├── run_scan single/multiscale hole detection
├── range_query points in bounding box
└── depth_for_accuracy
ZoneServer ── WebSocket + QUIC + io_uring ── sharded to 300k entities
Two-layer zone model: enum Zone (wire-safe, 6+ built-in shapes, serde) +
trait ZoneShape (custom dynamic shapes). Mix both in the same store.
| Feature | Provides |
|---|---|
| (default) | coord, zone, octree, store, scan — zero deps |
net |
Postcard wire codec, LZ4/ZSTD, dead-reckoning |
server |
WebSocket server + client, sharding, hysteresis debounce |
quic |
QUIC transport (quinn + rustls, datagrams) |
io_uring |
Linux io_uring transport (tokio-uring) |
pathfinding |
3D voxel A* over octree |
game |
GameWorld, LayeredMap, ChunkedGameWorld, PortalSystem |
terrain |
Marching cubes, OBJ/PLY export |
av |
EKF fusion, sensor FOV, safety envelope, HD map, V2X |
bevy |
Bevy ECS plugin (Spatial3dPlugin, ZoneTracker) |
embedded |
no_std linear-scan store |
lidar |
Pose/quaternion math, scan ingestion |
parallel |
Rayon-accelerated scanning |
geo |
geo-types interop |
prometheus |
Metrics exporter |
mimalloc |
MiMalloc global allocator |
plozone = { version = "0.1", features = ["server", "quic"] }| Transport | Feature | Latency p99 | Use case |
|---|---|---|---|
| WebSocket | server |
~5 ms | Browser clients |
| QUIC | quic |
~2 ms | Mobile, 0-RTT reconnect |
| io_uring | io_uring |
< 1 ms | Linux, max throughput |
All share the same postcard wire format and ZoneServer core.
| Tier | Entities | Latency p99 |
|---|---|---|
| Single process | ~5k | < 5 ms |
| Sharded ×16 | ~80k | < 2 ms |
| Sharded ×64 + io_uring | ~300k | < 1 ms |
| Multi-process | 5M+ | < 5 ms |
| Operation | Time |
|---|---|
| 1k zone point query | ~730 ns |
| 1k octree insert | ~435 µs |
| Hole scan depth 4 | ~12 µs |
| WGS84 → ENU | ~128 ns |
| ENU → WGS84 | ~655 ns |
cargo build # core (zero deps)
cargo test --features full # 105 tests
cargo bench --features full # criterion
cargo clippy --features full -- -D warningsMIT. See LICENSE.