From d6fe0f3805ad2f6eefb68606d14e531129015fef Mon Sep 17 00:00:00 2001 From: German Khokhlov Date: Fri, 16 Oct 2026 22:19:57 +0400 Subject: [PATCH] fix(globe): the floor takes no tile coarser than 1 km Review of Task 6: from 15 km with cold tiles Navara answers from 3.5-4 km tiles (13.9 km at AUS), below the 4 km floor limit, 6-16 m off; the mesh floor samples up to 25 km, so those would latch. MAX_FLOOR_TILE_SIZE_M is now 1 km: from 800 m the answering tiles are 112-314 m. The 1.8 km tile that read the Austin ground right under a 600 m camera is now a miss too, which only leaves the DEM prior in place. qa-surface-heights runs the 15 km pass first in a fresh page (cold), then the 800 m pass in another, and keeps every answer the floor rule would take while the tiles stream. Measured: 800 m 19/20 within 2 m of Cesium; 15 km cold 7/20 (the plan's gate of 15 assumed warm tiles - lod 'finest' can only use what Navara has loaded, and at 15 km it loads 3.5-14 km tiles), and the floor rule takes 0/20 of those; while streaming it took answers more than 2 m off at 3 places: the Empire State spire (39 m, also the settled answer) and two street points 2.2-2.3 m off. --- src/data/meshFloorSampler.test.mjs | 7 ++++++- src/services/groundSnap.test.mjs | 2 +- src/services/meshFloorSampler.js | 15 ++++++++++----- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/data/meshFloorSampler.test.mjs b/src/data/meshFloorSampler.test.mjs index f518dac42..1ab53b9b4 100644 --- a/src/data/meshFloorSampler.test.mjs +++ b/src/data/meshFloorSampler.test.mjs @@ -154,7 +154,12 @@ test('sampler: a coarse tile answer is a miss; a fine one latches', async () => engine.fake.script('sampleHeightDetailed', () => ({ height: 143.2, source: 'tiles', tileSizeM: 27_914 })); sampleMeshFloorCells(engine, [cell], opts); assert.equal(cachedMeshFloor(cell.lat, cell.lon), null, 'coarse: no latch'); - engine.fake.script('sampleHeightDetailed', () => ({ height: 122.5, source: 'tiles', tileSizeM: 1_797 })); + // A 3.5 km tile from 15 km, cold, read 16 m off: still too coarse. + engine.fake.script('sampleHeightDetailed', () => ({ height: 138.7, source: 'tiles', tileSizeM: 3_456 })); + sampleMeshFloorCells(engine, [cell], opts); + assert.equal(cachedMeshFloor(cell.lat, cell.lon), null, '3.5 km: no latch'); + // The tiles answering from 800 m are 112-314 m. + engine.fake.script('sampleHeightDetailed', () => ({ height: 122.5, source: 'tiles', tileSizeM: 241 })); sampleMeshFloorCells(engine, [cell], opts); assert.equal(cachedMeshFloor(cell.lat, cell.lon), 122.5); const terrainOnly = nextSite(); diff --git a/src/services/groundSnap.test.mjs b/src/services/groundSnap.test.mjs index 2cff50c76..7af9207d2 100644 --- a/src/services/groundSnap.test.mjs +++ b/src/services/groundSnap.test.mjs @@ -71,7 +71,7 @@ test('a coarse tile answer or only terrain is a miss; a viewer reaches its engin engine.fake.script('sampleHeightDetailed', () => ({ height: 122.5, source: 'tiles', - tileSizeM: 1_797, + tileSizeM: 241, })); const viewer = {}; const unregister = registerViewerEngine(viewer, engine); diff --git a/src/services/meshFloorSampler.js b/src/services/meshFloorSampler.js index 92c76f783..907361dce 100644 --- a/src/services/meshFloorSampler.js +++ b/src/services/meshFloorSampler.js @@ -2,11 +2,16 @@ import * as geo from '../geo/index.js'; import { engineFromViewer } from '../globe/cesium/engineFromViewer.js'; import { acceptedSurfaceHeight } from '../globe/surfaceDetail.js'; -/** Answers from tiles larger than this are too coarse to latch (m): on - * Navara at Austin a 1.8 km tile read the ground (122.5 m) and the 28 km - * tile shown while streaming read 143.2 m. Cesium does not size its - * answers, so its gates are the camera height and tilesLoaded below. */ -export const MAX_FLOOR_TILE_SIZE_M = 4000; +/** Answers from tiles larger than this are too coarse to latch (m). + * Measured on Navara (scripts/qa-surface-heights.mjs): from 800 m the + * answering tiles were 112-314 m and within 2 m of Cesium; from 15 km, cold, + * 3.5-4 km tiles were off by -16.2 to +6.2 m; while streaming a 27.9 km tile + * read 143.2 m at Austin where the ground is 122.5 m. A 1.8 km tile at + * Austin (the hidden tile under a 600 m camera looking ahead) read the + * ground right, but 1 km keeps every measured coarse error out; such a miss + * only leaves the DEM prior in place. Cesium does not size its answers, so + * its gates are the camera height and tilesLoaded below. */ +export const MAX_FLOOR_TILE_SIZE_M = 1000; /** Construct an instance-owned meshFloorSampler service with explicit dependencies. */ export function createMeshFloorSampler({