plozone 0.1.2

3D spatial zone engine: geofencing, octree hole-scanning, realtime sync (WebSocket + QUIC + io_uring), voxel pathfinding, and AV sensor fusion.
Documentation
<!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(&amp;[
    ZoneEntry::new(1, Zone::cylinder(10.7626, 106.6601, 50.0)
        .with_z_range(0.0, 20.0)
        .build()),
], &amp;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, &amp;conv);
assert_eq!(hits.as_slice(), &amp;[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(&amp;octree, &amp;store, 1, &amp;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 &lt;1 &mu;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 &lt;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 &amp; 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 &mu;s</td></tr>
      <tr><td>Hole scan depth 4</td><td>~12 &mu;s</td></tr>
      <tr><td>Coord WGS84 &rarr; ENU</td><td>~128 ns</td></tr>
      <tr><td>Coord ENU &rarr; 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>&lt; 5 ms</td><td>1 server</td></tr>
      <tr><td>Sharded (16), tokio</td><td>~80k</td><td>~100k</td><td>&lt; 2 ms</td><td>1 server</td></tr>
      <tr><td>Sharded (64), io_uring</td><td>~300k</td><td>~500k</td><td>&lt; 1 ms</td><td>1 server</td></tr>
      <tr><td>Multi-process cluster</td><td>~5M+</td><td>unlimited</td><td>&lt; 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> &middot;
    <a href="https://crates.io/crates/plozone">crates.io</a> &middot;
    <a href="https://docs.rs/plozone">docs.rs</a>
  </p>
</footer>

</body>
</html>