See More Details

TempleScan, a LiDAR Heritage Scanning App for iOS

An iOS app that captures 3D meshes of heritage structures with the LiDAR sensor, guided by live coverage feedback, and exports them to standard formats.

2026
iOS

Overview

TempleScan is an iOS app for documenting heritage structures with the LiDAR sensor on recent iPhones and iPads. You create a project for a site, scan a target, review and annotate the resulting mesh, and export it — the goal being a repeatable record of a structure's condition rather than a one-off 3D model.

The app is organized as feature modules (scanner, review, projects, timeline, annotations, history, settings) over a core layer that holds AR session management, geometry, processing, export, persistence and networking. It's about 7,500 lines of Swift with a test suite covering the parts that can be tested without a camera: the coverage grid, the scanner state machine, the guidance engine, mesh export and raycasting, and every persistence path.

It is an MVP, and the code is explicit about where the roadmap stops. Scan-to-scan comparison — registration, ICP alignment, a change heatmap — exists as protocols and data types so two scans of the same target can be compared later without a data-model migration, but nothing behind it is implemented and the Compare action says so.

Highlights

  • LiDAR scanning built on ARKit scene reconstruction, with mesh anchors collected and merged into a single exportable model.
  • A live coverage grid and guidance engine that tell you which parts of the target are still unscanned, backed by a tracking-quality monitor that warns when conditions degrade.
  • Export to OBJ, PLY and USDZ, with a PLY reader for re-importing previous captures.
  • SwiftData persistence for projects, scan sessions and pinned annotations, with on-device thumbnail generation and mesh statistics.
  • Mesh raycasting so annotations can be placed by tapping a point on the captured geometry.
  • A sync queue and API client scaffolded for a future backend, with scans working entirely offline today.

Design Notes

01

Coverage feedback during the scan, not after it

The failure mode of handheld scanning is discovering a hole in the mesh once you've already left the site. A coverage grid is analyzed live as mesh anchors arrive and drives a guidance engine that points you at the gaps, so the scan is verified while you can still fix it.

02

A state machine for the scan session

Scanning has more states than 'running' — waiting for tracking, degraded tracking, capturing, paused, finished, failed — and each has different valid transitions. Those live in a testable ScannerStateMachine rather than as booleans in the view model, so the guidance and UI can be verified without an ARKit session.

03

Three export formats for three consumers

OBJ is the lowest common denominator for mesh tools, PLY carries per-vertex data and round-trips back into the app through its own reader, and USDZ is what a colleague can open by tapping the file on an iPhone. Each has a separate exporter behind one coordinator rather than one format being converted into the others.

04

Comparison is stubbed on purpose

Change detection between two scans is the point of the app long-term, and it is genuinely hard — registration, ICP alignment, distance computation, then classifying the deltas as crack growth, material loss, vegetation or deformation. Rather than ship a weak on-device version, the types and protocols are defined now so the persisted data model already accommodates it, with a note that the real pipeline likely belongs in a processing service rather than on the phone.

05

Offline first, sync later

A scan happens at a site, which is exactly where connectivity is worst. Everything is written to SwiftData locally and a sync queue sits in front of the API client, so the networking layer can be filled in later without changing how the capture path behaves.