fix(transit): a held vehicle's snapshot height is its drawn marker's while the frame pass places it

Near the ground the marker follows the terrain sampled between two reports,
which a straight blend of the reports' floors misses over uneven ground.
This commit is contained in:
Sameh Khamis committed 2026-11-13 18:36:42 -08:00
1 parent 4bb7b411e9
commit 6c55daf9ac
3 files changed
+25 -5

No files matched your search

+2 -2
View File
@@ -2277,8 +2277,8 @@ offers the same for a vehicle (`getSelectedVehicle`, `getCockpitSubject`,
out of the camera's view, and its sprite, 3D model, card, trail and detection
box are hidden; released, it is out of play until a visibility sweep finds it in
view. Its snapshot's `position.groundHeightM` is the floor where playback draws
it (its segment's two reports' floors at the playback fraction), not the newest
report's, and null while that floor is unknown. Rail's `path.direction` is the
it (the drawn marker's height while it is placed, else its segment's two
reports' floors at the playback fraction), not the newest report's, and null while that floor is unknown. Rail's `path.direction` is the
way the drawn train runs: once playback has placed it, a report that runs back
turns it only when playback reaches that report. `docs/APPLICATION.md` (Cockpit subjects) shows a minimal provider. `src/ui/cockpitSubjectView.test.mjs`,
`src/cockpitSubjectProviders.test.mjs`, `src/cockpitProgress.test.mjs`,
+19 -2
View File
@@ -1,3 +1,4 @@
import * as Cesium from 'cesium';
import {
getRegisteredTransitFeed,
transitRouteLabel,
@@ -77,9 +78,12 @@ export function createTransitCockpitSubject({ state, parts, services }) {
return reuse(previous, next);
}
const scratchCartographic = new Cesium.Cartographic();
/**
* The floor under the vehicle where playback draws it: its segment's two
* reports' floors at the playback fraction, without the shared lift. Null
* The floor under the vehicle where playback draws it, without the shared
* lift: the drawn marker's height while the frame pass places it (in view,
* or held), which near the ground follows the terrain between reports;
* else its segment's two reports' floors at the playback fraction. Null
* while either floor is unknown, as on cold terrain, so a view waits for
* the surface. Not `entry.heightM`, the floor at the newest report, which
* playback has not reached yet.
@@ -87,6 +91,19 @@ export function createTransitCockpitSubject({ state, parts, services }) {
function drawnFloorOf(entry) {
const segment = entry.segment;
if (!segment || entry.heightPending) return null;
const placed =
entry.surfaceReady === true &&
entry.hasRendered &&
entry.marker?.position &&
(state._visible.has(entry) || entry.key === state._cockpitSubjectKey);
if (placed) {
const drawn = Cesium.Cartographic.fromCartesian(
entry.marker.position,
undefined,
scratchCartographic,
);
if (drawn) return drawn.height - liftM;
}
const from = segment.from?.h;
const to = segment.to?.h;
if (!Number.isFinite(from) || !Number.isFinite(to)) return null;
+4 -1
View File
@@ -4247,7 +4247,10 @@ test('the selected vehicle reads as a snapshot of its place, motion and source',
assert.equal(view.provenance.positionSource, 'gps');
assert.deepEqual(view.stop, { stopId: 'place-1', status: 'IN_TRANSIT_TO' });
const entry = app.vehicles()[0];
assert.equal(view.position.groundHeightM, entry.heightM - 1.5);
// Where it is drawn, without the shared lift (read back from the marker).
assert.ok(
Math.abs(view.position.groundHeightM - (entry.heightM - 1.5)) < 1e-3,
);
assert.ok(Number.isFinite(view.position.latitude));
});