From point cloud to city model. New

Feed the platform a LiDAR point cloud and building footprints and get back automatic LoD1.2 / LoD1.3 / LoD2.2 building models, rendered on the map as native mesh graphics — powered by the roofer engine behind the Dutch 3D BAG. Add a 30-command forestry LiDAR toolkit and a complete Gaussian splat pipeline, from training to a synced 3D viewer.

LoD1.2 / 1.3 / 2.2LAS / LAZ / COPCCityJSONSeq FUSION/LDV · 30 commandsGaussian splatsiTowns + Spark viewer
Building reconstruction

The 3DBAG engine, on your desktop

roofer is the fully automatic reconstruction tool behind the Dutch 3D BAG — roughly 10 million buildings nationwide. VoltGrid drives it end to end: pick a point cloud (.las / .laz / .copc.laz) and a 2D footprint polygon GeoPackage, choose a level of detail, and the resulting CityJSONSeq buildings appear on the map as esri/geometry/Mesh graphics — no manual modelling in the loop.

  • Guided native workflow — Tools → 🏠 Roofer: capability check, point-cloud picker, footprint picker, LoD prompt (1.2 / 1.3 / 2.2 — default 2.2).
  • Async jobs — reconstruction runs in the background, typically 1–10 minutes per city block depending on point density and CPU.
  • Native rendering — CityJSONSeq is fan-triangulated and reprojected to WGS84 when needed, one mesh per building on a roofer-buildings layer.
  • Scriptable — the same pipeline is exposed over REST, multipart upload, and window.MapApp.runRooferReconstruction.
http://localhost:5059
# probe → reconstruct → poll → fetch
GET  /api/roof/capabilities   → always 200
POST /api/roof/reconstruct
     { pointCloudPath, footprintGpkgPath,
       lod: "2.2" }
GET  /api/roof/jobs/{jobId}
{ "status": "complete", "buildingCount": 312 }
GET  /api/roof/jobs/{jobId}/output
→ CityJSONSeq, one fragment per line
Honest by design

Optional CLI, graceful degradation, clean licensing

roofer is an optional external dependency, invoked as a separate process. The app never bundles it — and never breaks without it.

🛡️

Graceful 503 contract

Without roofer installed, /api/roof/capabilities reports {available:false} and POST /api/roof/reconstruct returns 503 with an install hint — the rest of the app is unaffected.

⚖️

GPLv3, kept at arm's length

roofer is GPLv3. The app invokes it as a separate process and consumes its CityJSONSeq output, so GPLv3 does not extend to the app. Redistribute roofer's binary yourself and you take on GPLv3 attribution and source-offer obligations.

📥

Real-world inputs

Aerial LiDAR or dense image matching (AHN4, USGS 3DEP) plus cadastral footprints (Dutch BAG pand, OSM building=*) with a stable building-id column.

🧮

Safety caps

MaxBuildings (default 5000) caps in-map mesh count — above ~10k Mesh graphics become unwieldy. Raise it in appsettings.json for larger datasets.

🌲

FUSION/LDV forestry toolkit

A 30-command forestry LiDAR toolkit — ground filtering, canopy analysis, tree segmentation — sits alongside roofer in the platform's Point Cloud & 3D Reconstruction suite.

🗂️

Established sidecar pattern

roofer follows the platform's proven external-CLI pattern: 3-tier CLI resolution (config path → PATH → runtimes dir), an availability probe, and async-job bookkeeping over REST.

Gaussian splat training

Photos or video in, splat out — on your hardware

The splat training pipeline turns photo sets or video into Gaussian splats on-device, then drops the result straight into the 3D viewer. Two interchangeable backends sit behind one API — the provider is a config switch, and both run as separate subprocesses.

  • Postshot — built-in SfM, simplest path. Proprietary, Studio-tier license; requires an NVIDIA GPU (CC 7.5+ / RTX 2060+).
  • COLMAP + OpenSplat — the free, open route. Runs on CUDA, AMD ROCm, Apple Metal, or CPU (~100× slower). OpenSplat is AGPLv3, invoked as a separate, unmodified subprocess; COLMAP is BSD-3-Clause.
  • Live job tracking — jobs move Queued → Sfm → Training → Exporting → Completed, with progress in the viewer's Training Jobs panel and over REST.
  • Georeferencing — raw splats carry no CRS; place them with a georef field at train time or via POST /api/splats/{id}/meta.
http://localhost:5059
# which trainers are installed?
GET  /api/splats/train/availability
{ "postshot": true, "opensplat": false }

# multipart: photos/video + name, provider, steps…
POST /api/splats/train        → 202 + job
GET  /api/splats/train/jobs/{id}
{ "status": "Training", "progress": 42 }

# done → registered in /api/splats + viewer
Splat & 3D Tiles viewer

iTowns + Spark, synced to your map

A hardware-accelerated WebView2 viewer renders Gaussian splats via Spark and OGC 3D Tiles via iTowns — served entirely by the in-process local server, with the camera kept in sync with the main ArcGIS SceneView.

Every splat format

Upload .ply / .splat / .ksplat / .spz / .rad via POST /api/splats. Spark 2.x streams paged .rad LoD datasets of 100M+ splats.

🧱

OGC 3D Tiles

Drop a .zip tileset or .3tz; it's unpacked server-side and served from /api/3dtiles/<id>/tileset.json into iTowns' native OGC3DTilesLayer.

🎥

Camera sync

The viewer and the main ArcGIS map publish/subscribe camera state over /api/sync/camera plus an SSE stream — move either window and the other follows, echo-back suppressed.

🌍

Globe or planar scenes

Switch between a Globe scene (EPSG:4978 ECEF, place splats by lon/lat) and a projected planar scene positioned in meters.

🔒

Air-gapped by default

three, iTowns, and Spark are vendored locally and served by the in-process server — no runtime CDN calls, matching the platform's LAN-first posture.

Hardware-accelerated WebGL

The viewer runs in WebView2 on the Edge runtime with GPU-accelerated WebGL by default — the right substrate for GPU-heavy splatting.

Performance statements are workload-dependent: reconstruction time varies with point density and CPU; CPU-only splat training is roughly 100× slower than GPU; COLMAP SfM alone can take 10+ minutes for ~100 photos. Trainer availability depends on separately installed third-party binaries and their licenses.

Turn your LiDAR into living 3D.

Reconstruct buildings from the point clouds you already have, analyze forests with FUSION/LDV, and capture reality as Gaussian splats — all from one desktop, no cloud required.