SpatialEngine
Your tools
The 4D foundation your engineers build on. Edit billions of voxels interactively, version every project, and extend the engine in any language to develop exactly the tools your work needs.
Interactive SpatialEngine examples
Each example pairs a readable Python snippet with the live project it drives. SpatialEngine's extension system also supports native, web, and server interfaces in the language your team uses.
# Synthetic terrain, scanned into 640,000 points.
#
# Sums a few octaves of sine to get a ridged landscape, samples it on a jittered
# grid the way an airborne scan would, and colours the cloud by elevation.
import math
import random
import tempfile
from pathlib import Path
import fdk
client = fdk.connect()
obj = client.std.object
SIDE, SPACING = 800, 2.5 # 800 x 800 samples, 2 km across
def elevation(x, y):
"""Three octaves of ridged sine, in metres."""
h = 120.0 * math.sin(x / 640.0) * math.cos(y / 520.0)
h += 45.0 * math.sin(x / 190.0 + 1.3) * math.cos(y / 160.0)
h += 12.0 * math.sin(x / 55.0) * math.sin(y / 47.0)
return h + 40.0 * abs(math.sin(x / 300.0 + y / 900.0))
random.seed(7)
csv_path = Path(tempfile.gettempdir()) / "terrain.csv"
lo, hi = math.inf, -math.inf
with open(csv_path, "w") as f:
print("x,y,z,elev", file=f)
for i in range(SIDE):
for j in range(SIDE):
# Jitter each sample so the cloud reads as a scan, not a lattice.
x = i * SPACING + random.uniform(-1.0, 1.0)
y = j * SPACING + random.uniform(-1.0, 1.0)
z = elevation(x, y)
lo, hi = min(lo, z), max(hi, z)
print(f"{x:.2f},{y:.2f},{z:.2f},{z:.2f}", file=f)
header = obj.representation.load_header_config_from_csv(path=str(csv_path)).unwrap()
rep = obj.representation.load_point_cloud_from_csv(
path=str(csv_path), header_config=header
).unwrap()
node = obj.unsafe.create_id_node(name="Terrain scan").unwrap()
obj.upsert_representation(node=node, new_representation={
"PointCloud": {
"data": rep["PointCloud"]["data"],
"appearance": {"Geometry": {
"point_size": 3.0,
# The ramp spans the real elevation range, so the colours are the map legend.
"appearance": {"attribute": "elev", "range": [lo, hi], "ramp": "Terrain"},
"filter": "None",
"opacity": 1.0,
}},
},
}).unwrap()
client.std.wait_for_scene_sync()
client.std.camera.zoom_extents(duration_seconds=1.5)
print(f"{SIDE * SIDE:,} points, elevation {lo:.0f} m to {hi:.0f} m.")
A few octaves of sine make a landscape. Sampling it on a jittered grid makes a scan, and the elevation column becomes the colour ramp.
Cut, query, and edit billions of attribute-rich voxels interactively across the full 4D foundation.
A WASM extension system lets your engineers extend the engine with any UI, in the language they prefer.
Every change is versioned with local undo and redo, and syncs to the cloud through SpatialDrive.
What SpatialEngine gives your application
Geometry, attributes, coordinate systems, and time sit in one runtime, so extensions and the interactive viewport operate on the same state.
One runtime for geometry, attributes, and time
A scene, its attributes, and its history are the same object. Nothing has to be exported between a processing step and the view your users work in.
Small statements with explicit results
Loading data, building scenes, running spatial math, and driving the camera use small statements that are easy to inspect, test, and compose.
Build the interface your users need
Use the client and extension system from native, web, or server software while keeping the underlying spatial state consistent.