feat(annotations): draw on the world by hand (#547)

Supersedes #235 by @cora-fresh-labs, ported onto the current component layout with fixes from review.

Verified before merge: format, package boundaries, unit suite, build, and the browser tracking suite; a browser harness for the change where one applies; adversarial review applied.

Future work (not in this PR): hand-drawn marks do not persist across a reload today, and neither do spoken annotations; there is no storage layer for marks. The natural home is Scenes: a drawing that belongs to a shot and persists per shot, so a scene animation can carry its own marks. Needs an owner.
Co-authored-by: Clint Borle <[email protected]>
This commit is contained in:
Bilawal Sidhu authored and GitHub committed 2026-09-14 19:59:26 -05:00
1 parent 409e27d7f9
commit 9fc8d1966b
32 files changed
+3313 -19

No files matched your search

+12
View File
@@ -2226,6 +2226,11 @@ export function createAnnotationResolver({
return {
lat: Cesium.Math.toDegrees(carto.latitude),
lon: Cesium.Math.toDegrees(carto.longitude),
// The height the pick actually landed on — a roof, a hillside, or 0 on
// the ellipsoid. Callers that only want a coordinate ignore it; the draw
// tool's live preview needs it, or the rubber band sinks to sea level
// while the pointer is on a hill.
height: Number.isFinite(carto.height) ? carto.height : 0,
};
}
@@ -2331,5 +2336,12 @@ export function createAnnotationResolver({
viewportBias,
placesNearViewRecovery,
resolveRegionRingForQuery,
// Scene helpers, not resolution: the manual draw tool turns a click into a
// world point with the same depth-aware cascade the agent's pixel fallback
// uses, and the engine samples the surface under a hand-placed mark. Both
// are exposed so there is ONE pick cascade in the app, not a second one
// written beside it.
pickWorldFromScreen,
sampleGroundHeight,
};
}