From point cloud to service-territory digital twin. New

Feed VoltGrid a LiDAR point cloud and building footprints and get back automatic LoD1.2 / LoD1.3 / LoD2.2 building models — every structure around your substations, corridors, and feeders, rendered on the map as native mesh graphics, powered by the roofer engine behind the Dutch 3D BAG. Add a 30-command LiDAR vegetation toolkit for right-of-way analysis and a complete Gaussian splat pipeline that turns substation walkdown photos into living 3D, from training to a synced viewer.

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

The 3DBAG engine, on your grid workstation

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 — the built context around your feeders and substations, with 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
Walkthrough · captured in-app

Reconstruct, then fly straight to it

Run Tools → Roofer (LoD2.2 Buildings) and the reconstructed buildings land on the map as mesh graphics — the camera drops from the globe onto the result. This run loaded 393 buildings; 17 were skipped for having too few points to model, reported plainly rather than silently dropped.

393 buildings loaded17 skipped · too few pointsLoD2.2 meshes on the map
Screen recording — Roofer run at LoD2.2: the load result reports 393 buildings, then the camera flies from the globe to the reconstructed meshes. Poster frame: the settled view over aerial imagery.
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 — the same public data that covers most service territories.

🧮

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 vegetation toolkit

A 30-command forestry LiDAR toolkit — ground filtering, canopy analysis, tree segmentation — puts real numbers behind right-of-way vegetation and encroachment work, right alongside roofer in the 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 — a substation walkdown, a drone orbit of a tower — 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 at the real substation 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 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. Walk the yard in 3D while the map keeps pace.

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, a natural fit for OT environments and air-gapped utility networks.

Hardware-accelerated WebGL

The viewer runs with GPU-accelerated WebGL by default — the right substrate for GPU-heavy splatting and massive datasets.

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 a living grid twin.

Reconstruct the buildings around your corridors from point clouds you already have, quantify ROW vegetation with FUSION/LDV, and capture substations as Gaussian splats — all from one desktop, no cloud required. Pair it with GRID State to keep the twin tied to the assets your utility manages.