Read the mesh floor where transit vehicles and grounded flights actually are

With readings kept per point, the floor a vehicle gets depends on which point
is probed and where it is read. Transit offered the sampler the first point of
each vehicle's path in a cell, usually its oldest fix there, so a vehicle that
stayed in one cell never had its current spot probed. It now offers the latest
point of the path in each cell, and the newest fix in the vehicle's own cell
(the selected vehicle's history is walked newest first).

The grounded-flight display clamp read the floor at its sticky cell's centre,
which now answers from the reading nearest the centre, not the contact. It
reads at the contact's own position, held inside the sticky cell so boundary
hysteresis still applies.
This commit is contained in:
Sameh Khamis committed 2026-11-09 14:51:35 -08:00
1 parent 04b8c856ad
commit 9bce41d3c6
5 files changed
+192 -13

No files matched your search

+10 -7
View File
@@ -1360,13 +1360,16 @@ the same way; a cell keeps at most sixteen). A read answers from the cell's
reading nearest the asked point, so a viaduct and the street beside it in one
cell keep their own heights; two readings within about 5 m of each other keep
the lower. A spot refused only because the cell's DEM prior was cold is tried
again later. Before this, one probe at the cell's centre latched for the
session, so a centre on a roof lifted everything in the cell (a Haymarket bus
drew 23.5 m above the street, on the garage roof) and a centre in the river put
Red Line trains on the Longfellow Bridge 6–9 m under the deck. Residual: the
probe is vertical, so a vehicle directly under a deck or a roof overhang reads
the structure above it, and a vehicle between readings takes the nearest one, so
its floor steps where the nearest reading changes.
again later. Transit offers the sampler the latest point of each vehicle's path
in a cell (its newest fix in its own cell), and the grounded-flight display
clamp reads at the contact, held inside its sticky cell. Before this, one probe
at the cell's centre latched for the session, so a centre on a roof lifted
everything in the cell (a Haymarket bus drew 23.5 m above the street, on the
garage roof) and a centre in the river put Red Line trains on the Longfellow
Bridge 6–9 m under the deck. Residual: the probe is vertical, so a vehicle
directly under a deck or a roof overhang reads the structure above it, and a
vehicle between readings takes the nearest one, so its floor steps where the
nearest reading changes.
## Vessel components and sources
+35
View File
@@ -20,9 +20,11 @@ import { setMilitaryLayerActive } from './militaryRegistry.js';
import {
GROUND_FLOOR_LIFT_M,
reportMeshFloorCell,
reportValidatedMeshFloorCell,
setMeshFloorPreferred,
_clearMeshFloorCellsForTest,
} from './groundFloor.js';
import { resolveEllipsoidalGround } from './terrainHeights.js';
import {
_setTrackedOverlayHostForTest,
destroyTrackedReadout,
@@ -1181,6 +1183,39 @@ test('display floor: a grounded contact that drifted onto a higher cell is lifte
assert.ok(Math.abs(Cesium.Math.toDegrees(c.longitude) + 97.6604) < 1e-6);
});
test('display floor: reads the reading nearest the contact, not the cell centre', async () => {
_clearDisplayFloorStateForTest();
_clearMeshFloorCellsForTest();
setMeshFloorPreferred(true);
const realFetch = globalThis.fetch;
globalThis.fetch = async () =>
new Response(JSON.stringify({ results: [{ ellipsoid: 120 }] }), {
status: 200,
headers: { 'Content-Type': 'application/json' },
});
try {
await resolveEllipsoidalGround([{ lat: 30.317, lon: -97.717 }]);
} finally {
globalThis.fetch = realFetch;
}
// A hangar roof over the cell's centre; the apron where the contact is.
assert.equal(reportValidatedMeshFloorCell(30.317, -97.717, 142), true);
assert.equal(reportValidatedMeshFloorCell(30.3173, -97.7173, 121), true);
const pos = Cesium.Cartesian3.fromDegrees(-97.7173, 30.3173, 100);
const out = _floorGroundedDisplayPositionForTest(
{ onGround: true },
pos,
false,
);
const c = _floorCarto(out);
assert.ok(
Math.abs(c.height - (121 + GROUND_FLOOR_LIFT_M)) < 0.05,
`height ${c.height} should be the apron's 121 + lift`,
);
_clearMeshFloorCellsForTest();
_clearDisplayFloorStateForTest();
});
test('display floor: an AIRBORNE contact over the same cell is never lifted', () => {
_clearDisplayFloorStateForTest();
_clearMeshFloorCellsForTest();
+24 -5
View File
@@ -37,6 +37,22 @@ import {
DISPLAY_CORRIDOR_FAIR_SHARE,
} from './policy.js';
/** Half a coarse floor cell (0.001°), less a margin so rounding keeps a
* clamped coordinate inside the cell. */
const HALF_CELL_DEG = 0.00049;
/**
* A coordinate held within half a cell of the cell's centre (the short way
* round for longitude), so a read lands in the given cell.
* @param {number} deg @param {number} centreDeg
* @returns {number}
*/
function clampToCell(deg, centreDeg) {
let d = deg - centreDeg;
d -= 360 * Math.round(d / 360);
return centreDeg + Math.max(-HALF_CELL_DEG, Math.min(HALF_CELL_DEG, d));
}
export function createMotion({
flightState,
services,
@@ -865,12 +881,15 @@ export function createMotion({
);
// Boundary hysteresis: a position jittering across a cell edge would flip
// floors at fleet-tick rate (see stickyFloorCell).
const cell = stickyFloorCell(
Cesium.Math.toDegrees(carto.latitude),
Cesium.Math.toDegrees(carto.longitude),
state?.cell,
const latDeg = Cesium.Math.toDegrees(carto.latitude);
const lonDeg = Cesium.Math.toDegrees(carto.longitude);
const cell = stickyFloorCell(latDeg, lonDeg, state?.cell);
// A cell holds rendered-surface readings at the points they were taken,
// so the floor is read where the contact is, held inside its sticky cell.
const floor = cachedGroundFloor(
clampToCell(latDeg, cell.lat),
clampToCell(lonDeg, cell.lon),
);
const floor = cachedGroundFloor(cell.lat, cell.lon);
const next = state || {
cell,
in: new Cesium.Cartesian3(),
+15 -1
View File
@@ -124,7 +124,14 @@ export function createHeight({ state, services, parts }) {
const cells = new Map();
const collect = (point, answer) => {
if (!onGround) return;
if (!cells.has(answer.cell))
// A cell keeps the last point offered in it: the path is walked
// oldest first, so that is where the vehicle is now or about to be,
// and the mesh sampler reads the surface there.
const held = cells.get(answer.cell);
if (held) {
held.lat = point.lat;
held.lon = point.lon;
} else
cells.set(answer.cell, {
lat: point.lat,
lon: point.lon,
@@ -136,6 +143,13 @@ export function createHeight({ state, services, parts }) {
const newest = entry.fixes.at(-1);
const answer = requestHeight(newest.lat, newest.lon, entry);
entry.heightCell = answer.cell;
// The selected vehicle's path also offers its history, newest segment
// first; the vehicle's own cell is read where its newest fix is.
const own = cells.get(answer.cell);
if (own) {
own.lat = newest.lat;
own.lon = newest.lon;
}
if (answer.height !== null) {
entry.heightM = answer.height;
entry.heightResolved = true;
+108
View File
@@ -2938,6 +2938,114 @@ test('mesh refinement reaches all 100 retained DEM cells within five poll budget
assert.equal(probed.size, 100);
});
test('mesh refinement probes the latest point the path offers in a cell', async (t) => {
const { createHeight } = await import('./height.js');
// Three points along one cell's stretch of path, oldest first.
const path = [
{ lat: 42.3611, lon: -71.0751 },
{ lat: 42.3612, lon: -71.0753 },
{ lat: 42.3614, lon: -71.0754 },
];
const entry = { key: 'train', to: path[0], fixes: [path.at(-1)] };
const probed = [];
const state = {
_enabled: true,
_selectedKey: null,
_visible: new Set([entry]),
_vehicles: new Map([[entry.key, entry]]),
_floorCursor: 0,
_heightDirty: new Set(),
_viewer: { camera: { positionCartographic: { height: 100 } } },
};
const height = createHeight({
state,
services: {
render: { governorRequestRender() {} },
ground: {
coarseFloorCoord: (lat, lon) => ({
lat: Number(lat.toFixed(3)),
lon: Number(lon.toFixed(3)),
}),
cachedGroundFloor: () => 10,
GROUND_FLOOR_LIFT_M: 1.5,
},
mesh: {
sampleMeshFloorCells(scene, points) {
probed.push(...points.map((p) => [p.lat, p.lon]));
},
},
},
parts: {
trails: {
prepareEntry(e, collect) {
if (collect)
for (const point of path)
collect(point, height.requestHeight(point.lat, point.lon));
},
},
rendering: { requestVisibility() {} },
},
});
t.after(() => height.clear());
height.anchorFloors();
assert.deepEqual(probed, [[42.3614, -71.0754]]);
});
test('the selected vehicle is probed at its newest fix in its own cell', async (t) => {
const { createHeight } = await import('./height.js');
// The selected path offers its active corridor first, then its history
// newest segment first, so the last offer in the cell is an older point.
const newest = { lat: 42.3614, lon: -71.0754 };
const offers = [
newest,
{ lat: 42.3612, lon: -71.0753 },
{ lat: 42.3611, lon: -71.0751 },
];
const entry = { key: 'train', to: offers[0], fixes: [newest] };
const probed = [];
const state = {
_enabled: true,
_selectedKey: entry.key,
_visible: new Set([entry]),
_vehicles: new Map([[entry.key, entry]]),
_floorCursor: 0,
_heightDirty: new Set(),
_viewer: { camera: { positionCartographic: { height: 100 } } },
};
const height = createHeight({
state,
services: {
render: { governorRequestRender() {} },
ground: {
coarseFloorCoord: (lat, lon) => ({
lat: Number(lat.toFixed(3)),
lon: Number(lon.toFixed(3)),
}),
cachedGroundFloor: () => 10,
GROUND_FLOOR_LIFT_M: 1.5,
},
mesh: {
sampleMeshFloorCells(scene, points) {
probed.push(...points.map((p) => [p.lat, p.lon]));
},
},
},
parts: {
trails: {
prepareEntry(e, collect) {
if (collect)
for (const point of offers)
collect(point, height.requestHeight(point.lat, point.lon));
},
},
rendering: { requestVisibility() {} },
},
});
t.after(() => height.clear());
height.anchorFloors();
assert.deepEqual(probed, [[42.3614, -71.0754]]);
});
test('selection churn releases past geometry on every retained vehicle', async (t) => {
const app = harness(t, { floorAt: () => 10 });
const { mergeHistory, seek } = await import('../../data/contactPlayback.js');