<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Plozone — 3D Spatial Zone Engine for Rust</title>
<style>
:root {
--bg: #0d1117;
--card: #161b22;
--border: #30363d;
--text: #e6edf3;
--dim: #8b949e;
--accent: #58a6ff;
--green: #3fb950;
--orange: #d2991d;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: var(--bg);
color: var(--text);
line-height: 1.6;
}
.hero {
padding: 80px 20px 60px;
text-align: center;
border-bottom: 1px solid var(--border);
}
.hero h1 {
font-size: 3.2rem;
font-weight: 800;
letter-spacing: -0.5px;
background: linear-gradient(135deg, var(--accent), #a371f7);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.hero p {
font-size: 1.25rem;
color: var(--dim);
max-width: 700px;
margin: 16px auto 0;
}
.hero .badges {
margin-top: 24px;
display: flex;
justify-content: center;
gap: 12px;
flex-wrap: wrap;
}
.hero .badge {
background: var(--card);
border: 1px solid var(--border);
border-radius: 6px;
padding: 6px 14px;
font-size: 0.85rem;
color: var(--dim);
}
.hero .cta {
margin-top: 32px;
display: flex;
justify-content: center;
gap: 16px;
}
.btn {
padding: 12px 28px;
border-radius: 8px;
font-size: 1rem;
font-weight: 600;
text-decoration: none;
transition: all 0.15s;
}
.btn-primary {
background: var(--accent);
color: #fff;
}
.btn-primary:hover { background: #4090f0; }
.btn-outline {
border: 1px solid var(--border);
color: var(--text);
}
.btn-outline:hover { border-color: var(--accent); }
main {
max-width: 1000px;
margin: 0 auto;
padding: 60px 20px;
}
section { margin-bottom: 64px; }
h2 {
font-size: 1.75rem;
margin-bottom: 20px;
padding-bottom: 8px;
border-bottom: 1px solid var(--border);
}
.features {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 20px;
}
.feature {
background: var(--card);
border: 1px solid var(--border);
border-radius: 10px;
padding: 24px;
}
.feature h3 { font-size: 1.1rem; margin-bottom: 8px; color: var(--accent); }
.feature p { color: var(--dim); font-size: 0.92rem; }
table {
width: 100%;
border-collapse: collapse;
margin-top: 16px;
}
th, td {
padding: 10px 16px;
text-align: left;
border-bottom: 1px solid var(--border);
}
th { color: var(--dim); font-weight: 600; font-size: 0.85rem; }
td { font-size: 0.92rem; }
pre {
background: var(--card);
border: 1px solid var(--border);
border-radius: 8px;
padding: 20px;
overflow-x: auto;
font-size: 0.88rem;
line-height: 1.5;
}
code { font-family: 'JetBrains Mono', 'Fira Code', monospace; }
.code-comment { color: #8b949e; }
.code-keyword { color: #ff7b72; }
.code-string { color: #a5d6ff; }
.code-fn { color: #d2a8ff; }
.comparison { margin-top: 24px; }
.comparison th:first-child, .comparison td:first-child { font-weight: 600; }
.check { color: var(--green); }
.cross { color: #f85149; }
.partial { color: var(--orange); }
footer {
text-align: center;
padding: 40px 20px;
color: var(--dim);
font-size: 0.85rem;
border-top: 1px solid var(--border);
}
footer a { color: var(--accent); text-decoration: none; }
@media (max-width: 600px) {
.hero h1 { font-size: 2.2rem; }
.hero p { font-size: 1.05rem; }
}
</style>
</head>
<body>
<div class="hero">
<h1>plozone</h1>
<p>
3D spatial zone engine — geofencing, octree hole-scanning, realtime sync,
voxel pathfinding, and AV sensor fusion — all in Rust.
</p>
<div class="badges">
<span class="badge">105 tests</span>
<span class="badge">6,100+ LOC</span>
<span class="badge">Edition 2024</span>
<span class="badge">MIT</span>
</div>
<div class="cta">
<a class="btn btn-primary" href="https://github.com/fentz26/plozone">GitHub</a>
<a class="btn btn-outline" href="https://docs.rs/plozone">Documentation</a>
<a class="btn btn-outline" href="https://crates.io/crates/plozone">crates.io</a>
</div>
</div>
<main>
<section>
<h2>Why Plozone?</h2>
<table class="comparison">
<tr><th>Feature</th><th>Plozone</th><th>OctoMap</th><th>Tile38</th><th>rstar</th></tr>
<tr><td>3D zone shapes</td><td class="check">full</td><td>voxel only</td><td>2D polygons</td><td>AABB only</td></tr>
<tr><td>Hole scanning</td><td class="check">octree-based</td><td class="check">yes</td><td class="cross">no</td><td class="cross">no</td></tr>
<tr><td>Dynamic zones (runtime)</td><td class="check">yes</td><td class="cross">no</td><td class="partial">partial</td><td class="cross">no</td></tr>
<tr><td>Realtime sync (WS + QUIC)</td><td class="check">yes</td><td class="cross">no</td><td class="check">WS</td><td class="cross">no</td></tr>
<tr><td>Game / arbitrary coords</td><td class="check">yes</td><td class="cross">no</td><td class="cross">no</td><td class="cross">no</td></tr>
<tr><td>AV stack (EKF, V2X, HD map)</td><td class="check">yes</td><td class="cross">no</td><td class="cross">no</td><td class="cross">no</td></tr>
<tr><td>no_std embedded</td><td class="check">yes</td><td class="cross">no</td><td class="cross">no</td><td class="partial">partial</td></tr>
<tr><td>Voxel pathfinding</td><td class="check">A*</td><td class="cross">no</td><td class="cross">no</td><td class="cross">no</td></tr>
<tr><td>Rust-native</td><td class="check">yes</td><td>C++ bindings</td><td>Go server</td><td class="check">yes</td></tr>
</table>
</section>
<section>
<h2>Quick Start</h2>
<pre><code><span class="code-comment">// Cargo.toml</span>
<span class="code-keyword">[dependencies]</span>
plozone = { version = <span class="code-string">"0.1"</span>, features = [<span class="code-string">"full"</span>] }
<span class="code-comment">// main.rs</span>
<span class="code-keyword">use</span> plozone::{
coord::EnuConverter,
store::ZoneStore,
zone::{Zone, ZoneEntry},
scan::{run_scan, ScanMode},
};
<span class="code-keyword">let</span> <span class="code-fn">conv</span> = EnuConverter::new(10.7626, 106.6601, 0.0);
<span class="code-keyword">let</span> <span class="code-fn">store</span> = ZoneStore::from_entries(&[
ZoneEntry::new(1, Zone::cylinder(10.7626, 106.6601, 50.0)
.with_z_range(0.0, 20.0)
.build()),
], &conv);
<span class="code-comment">// Point-in-zone query</span>
<span class="code-keyword">let</span> <span class="code-fn">hits</span> = store.query_geodetic(10.7626, 106.6601, 5.0, &conv);
assert_eq!(hits.as_slice(), &[1]);
<span class="code-comment">// Hole scan</span>
<span class="code-keyword">let</span> <span class="code-fn">octree</span> = OctreeNode::new([0.0; 3], 64.0);
<span class="code-keyword">let</span> <span class="code-fn">result</span> = run_scan(&octree, &store, 1, &ScanMode::Coarse { depth: 4 });
println!("coverage: {:.1}%", result.coverage_pct);</code></pre>
</section>
<section>
<h2>Features</h2>
<div class="features">
<div class="feature">
<h3>ZoneStore + R-tree</h3>
<p>Serializable Zone enum with 5+ built-in shapes + trait-based custom shapes. R-tree indexed for <1 μs point queries at 100k zones.</p>
</div>
<div class="feature">
<h3>Octree Hole Scanner</h3>
<p>Adaptive-density octree (depth 17 max, ~4mm voxels) with single-pass and multiscale hole detection. Coverage % reporting.</p>
</div>
<div class="feature">
<h3>Realtime Sync</h3>
<p>WebSocket + QUIC + io_uring transports. Sharded server to 300k entities at <1ms p99. Lock-free AtomicPos for position updates.</p>
</div>
<div class="feature">
<h3>Voxel Pathfinding</h3>
<p>3D A* over the octree. Works with zone-aware occupancy — doors, walls, cylindrical columns are all zones that block traversal.</p>
</div>
<div class="feature">
<h3>AV Stack</h3>
<p>EKF IMU fusion, sensor FOV zones (camera/lidar/radar), safety envelope, HD map lane graph, behaviour zones, V2X beacons.</p>
</div>
<div class="feature">
<h3>Game Coords</h3>
<p>GameWorld, LayeredMap, ChunkedGameWorld, PortalSystem — arbitrary coordinate systems via the CoordSystem trait. TiledWorld for planetary scale.</p>
</div>
<div class="feature">
<h3>Wire Protocol</h3>
<p>Postcard-encoded messages with LZ4/ZSTD compression. Dead-reckoning via PosTracker. Versioned wire snapshots for forward compatibility.</p>
</div>
<div class="feature">
<h3>Terrain & Mesh</h3>
<p>Marching cubes surface extraction from octree density. OBJ/PLY export, density export. TSDF/ESDF planned for v0.2.</p>
</div>
</div>
</section>
<section>
<h2>Performance</h2>
<table>
<tr><th>Operation</th><th>Time</th></tr>
<tr><td>Zone query (1k zones, R-tree)</td><td>~730 ns</td></tr>
<tr><td>Octree batch insert 1k pts</td><td>~435 μs</td></tr>
<tr><td>Hole scan depth 4</td><td>~12 μs</td></tr>
<tr><td>Coord WGS84 → ENU</td><td>~128 ns</td></tr>
<tr><td>Coord ENU → WGS84</td><td>~655 ns</td></tr>
</table>
</section>
<section>
<h2>Scale</h2>
<table>
<tr><th>Tier</th><th>Entities</th><th>Zones</th><th>Latency p99</th><th>Infra</th></tr>
<tr><td>Single process, tokio</td><td>~5k</td><td>~100k</td><td>< 5 ms</td><td>1 server</td></tr>
<tr><td>Sharded (16), tokio</td><td>~80k</td><td>~100k</td><td>< 2 ms</td><td>1 server</td></tr>
<tr><td>Sharded (64), io_uring</td><td>~300k</td><td>~500k</td><td>< 1 ms</td><td>1 server</td></tr>
<tr><td>Multi-process cluster</td><td>~5M+</td><td>unlimited</td><td>< 5 ms</td><td>LB + N servers</td></tr>
</table>
</section>
</main>
<footer>
<p>Plozone is MIT-licensed. Made with Rust.</p>
<p>
<a href="https://github.com/fentz26/plozone">GitHub</a> ·
<a href="https://crates.io/crates/plozone">crates.io</a> ·
<a href="https://docs.rs/plozone">docs.rs</a>
</p>
</footer>
</body>
</html>