fix(infrastructure): test ground below 0 m and unknown terrain correctly

The ellipsoidal horizon test hid ground below the ellipsoid (low-geoid
coasts, the Dead Sea) from a camera near it, so it is now tested at 0 m.
With the globe hidden the ground is tested as the vertical from 0 to
9,000 m against the frustum planes, in place of a 4.5 km sphere that let
in much unseen ground.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
quanticsoul4772andClaude Opus 5.5 committed 2026-10-29 01:47:05 -07:00
1 parent ecc0ced47c
commit f392eecbd9
3 files changed
+101 -57

No files matched your search

+6 -5
View File
@@ -1959,11 +1959,12 @@ during continuous motion. Disable/re-enable resets selection cleanly.
Close-up stem sizing uses camera-to-feature distance without a 5 km minimum. Close-up stem sizing uses camera-to-feature distance without a 5 km minimum.
Unchanged overlay entries do not request another frame; moved positions, Unchanged overlay entries do not request another frame; moved positions,
changed membership and re-enabling still publish. Ground sampling waits for changed membership and re-enabling still publish. Ground sampling waits for
visible globe tiles to settle, samples only markers whose ground is in the visible globe tiles to settle, and skips markers whose ground the camera
camera's view and above the horizon (unseen ground reads through the Earth cannot see (unseen ground reads through the Earth and would retry every 2 s).
and would retry every 2 s; until it is seen, a stem keeps its unsampled Ground is tested at loaded globe terrain, or across 0-9,000 m when the globe
height, which can show for a stem whose base is just off screen), and uses is hidden, so photoreal views skip only ground well out of view. Until it is
valid loaded terrain as a floor while seen, a stem keeps its unsampled height, which can show for a stem whose base
is just off screen. Sampling uses valid loaded terrain as a floor while
retaining rooftop and below-sea-level elevations. A hidden globe does not retaining rooftop and below-sea-level elevations. A hidden globe does not
constrain photoreal geometry, and retry work remains bounded. Already sampled constrain photoreal geometry, and retry work remains bounded. Already sampled
nearby markers follow higher settled terrain on existing bounded walks, without nearby markers follow higher settled terrain on existing bounded walks, without
+57 -21
View File
@@ -113,8 +113,13 @@ async function createRealLocalLayerHarness({
upWC: new Cesium.Cartesian3(), upWC: new Cesium.Cartesian3(),
frustum: { frustum: {
fov: Math.PI / 3, fov: Math.PI / 3,
// No planes: everything is in view. One plane no point satisfies:
// nothing is.
computeCullingVolume: () => ({ computeCullingVolume: () => ({
computeVisibility: () => baseVisibility, planes:
baseVisibility === Cesium.Intersect.OUTSIDE
? [new Cesium.Cartesian4(0, 0, 0, -1)]
: [],
}), }),
}, },
moveEnd, moveEnd,
@@ -787,29 +792,24 @@ test('an unseen base is not sampled and arms no retry until it is in view', asyn
assert.ok(Math.abs(baseHeightM(env) - 117) < 0.01); assert.ok(Math.abs(baseHeightM(env) - 117) < 0.01);
}); });
for (const [label, globe] of [ /**
['loaded terrain', { show: true, tilesLoaded: true, getHeight: () => 2_500 }], * Give the harness a real Cesium camera `southM` metres south of the base at
['a hidden globe', { show: false, tilesLoaded: true, getHeight: () => undefined }], * `cameraM` metres above the ellipsoid, looking at the base's ground at
]) { * `groundM` (or directly away from it).
test(`high ground in view is sampled with ${label} although its unsampled base projects off screen`, async (t) => { */
// A base on 2,500 m terrain, seen from 3 km away at a shallow angle: its function aimRealCamera(env, { groundM, cameraM, southM, away = false }) {
// ellipsoid-height point is far below the bottom of the screen.
const env = await createRealLocalLayerHarness({
sampleHeightSupported: true, sampleHeight: () => 2_500,
});
const clock = installFakeClock(t);
t.after(() => { env.layer.destroy(env.viewer); env.cleanup(); });
env.viewer.scene.globe = globe;
const entity = env.dataSources[0].entities.values[0]; const entity = env.dataSources[0].entities.values[0];
const base = Cesium.Cartographic.fromCartesian(entity.__localBaseCartesian); const base = Cesium.Cartographic.fromCartesian(entity.__localBaseCartesian);
const ground = Cesium.Cartesian3.fromRadians(base.longitude, base.latitude, 2_500); const ground = Cesium.Cartesian3.fromRadians(base.longitude, base.latitude, groundM);
const position = Cesium.Cartesian3.fromRadians( const position = Cesium.Cartesian3.fromRadians(
base.longitude, base.longitude,
base.latitude - 3_000 / 6_371_000, base.latitude - southM / 6_371_000,
2_500 + 1_000, cameraM,
); );
const direction = Cesium.Cartesian3.normalize( const direction = Cesium.Cartesian3.normalize(
Cesium.Cartesian3.subtract(ground, position, new Cesium.Cartesian3()), away
? Cesium.Cartesian3.subtract(position, ground, new Cesium.Cartesian3())
: Cesium.Cartesian3.subtract(ground, position, new Cesium.Cartesian3()),
new Cesium.Cartesian3(), new Cesium.Cartesian3(),
); );
const right = Cesium.Cartesian3.normalize( const right = Cesium.Cartesian3.normalize(
@@ -833,18 +833,54 @@ for (const [label, globe] of [
upWC: up, upWC: up,
frustum, frustum,
}); });
const offScreen = frustum return frustum
.computeCullingVolume(position, direction, up) .computeCullingVolume(position, direction, up)
.computeVisibility(new Cesium.BoundingSphere(entity.__localBaseCartesian, 1)); .computeVisibility(new Cesium.BoundingSphere(entity.__localBaseCartesian, 1));
assert.equal(offScreen, Cesium.Intersect.OUTSIDE, 'precondition: the ellipsoid-height base is off screen'); }
const loadedTerrain = (height) => ({ show: true, tilesLoaded: true, getHeight: () => height });
const hiddenGlobe = { show: false, tilesLoaded: true, getHeight: () => undefined };
for (const { label, globe, groundM, cameraM, southM, baseOffScreen } of [
// 2,500 m terrain from 3 km away at a shallow angle: the ellipsoid-height
// base is far below the bottom of the screen.
{ label: 'high ground with loaded terrain', globe: loadedTerrain(2_500), groundM: 2_500, cameraM: 3_500, southM: 3_000, baseOffScreen: true },
{ label: 'high ground under a hidden globe', globe: hiddenGlobe, groundM: 2_500, cameraM: 3_500, southM: 3_000, baseOffScreen: true },
// A low-geoid coast (about -63 m near Mumbai) from a camera 50 m above the
// ellipsoid: the ellipsoidal horizon would hide the ground itself.
{ label: 'ground below the ellipsoid', globe: loadedTerrain(-63), groundM: -63, cameraM: 50, southM: 2_000, baseOffScreen: false },
]) {
test(`${label} in view is sampled`, async (t) => {
const env = await createRealLocalLayerHarness({
sampleHeightSupported: true, sampleHeight: () => groundM,
});
const clock = installFakeClock(t);
t.after(() => { env.layer.destroy(env.viewer); env.cleanup(); });
env.viewer.scene.globe = globe;
const baseVisibility = aimRealCamera(env, { groundM, cameraM, southM });
if (baseOffScreen)
assert.equal(baseVisibility, Cesium.Intersect.OUTSIDE, 'precondition: the ellipsoid-height base is off screen');
clock.advance(2_100); clock.advance(2_100);
env.preRender.raise(); env.preRender.raise();
assert.equal(env.sampleCalls.count, 1, 'the ground in view is sampled'); assert.equal(env.sampleCalls.count, 1, 'the ground in view is sampled');
assert.ok(Math.abs(baseHeightM(env) - 2_500) < 0.01); assert.ok(Math.abs(baseHeightM(env) - groundM) < 0.01);
}); });
} }
test('under a hidden globe, ground behind the camera is not sampled', async (t) => {
const env = await createRealLocalLayerHarness({
sampleHeightSupported: true, sampleHeight: () => 2_500,
});
const clock = installFakeClock(t);
t.after(() => { env.layer.destroy(env.viewer); env.cleanup(); });
env.viewer.scene.globe = hiddenGlobe;
aimRealCamera(env, { groundM: 2_500, cameraM: 3_500, southM: 3_000, away: true });
clock.advance(2_100);
env.preRender.raise();
assert.equal(env.sampleCalls.count, 0);
});
test('settled terrain refinement lifts an already sampled stem without another GPU sample', async (t) => { test('settled terrain refinement lifts an already sampled stem without another GPU sample', async (t) => {
const env = await createRealLocalLayerHarness({ const env = await createRealLocalLayerHarness({
sampleHeightSupported: true, sampleHeight: () => 117, sampleHeightSupported: true, sampleHeight: () => 117,
+38 -31
View File
@@ -1131,17 +1131,25 @@ function refreshLocalTerrainFloor(viewer, record) {
return true; return true;
} }
const groundSampleSphere = new Cesium.BoundingSphere(
new Cesium.Cartesian3(),
1,
);
const groundSampleOccluder = new Cesium.EllipsoidalOccluder( const groundSampleOccluder = new Cesium.EllipsoidalOccluder(
Cesium.Ellipsoid.WGS84, Cesium.Ellipsoid.WGS84,
); );
const groundSampleCarto = new Cesium.Cartographic(); const groundSampleCarto = new Cesium.Cartographic();
const groundSampleTop = new Cesium.Cartesian3(); const groundSampleLow = new Cesium.Cartesian3();
const groundSampleHigh = new Cesium.Cartesian3();
/** The record's vertical at `height` metres above the ellipsoid. */
function groundSamplePoint(record, height, result) {
groundSampleCarto.longitude = record.carto.longitude;
groundSampleCarto.latitude = record.carto.latitude;
groundSampleCarto.height = height;
return Cesium.Cartographic.toCartesian(
groundSampleCarto,
Cesium.Ellipsoid.WGS84,
result,
);
}
/** /**
* Whether the camera can see the ground under the record: inside the view * Whether the camera can see the ground under the record: inside the view
@@ -1150,10 +1158,10 @@ const groundSampleTop = new Cesium.Cartesian3();
* the Earth (about -6,344 km near Ashburn on Esri) and fails on every 2 s * the Earth (about -6,344 km near Ashburn on Esri) and fails on every 2 s
* retry, each one a full offscreen render; 110 unseen data centres there held * retry, each one a full offscreen render; 110 unseen data centres there held
* rest frames at 58-589 ms. Unsampled bases sit on the ellipsoid, so the test * rest frames at 58-589 ms. Unsampled bases sit on the ellipsoid, so the test
* uses loaded globe terrain when there is some, and otherwise every height a * uses loaded globe terrain when there is some. Otherwise (a hidden globe) it
* sample can accept (0 to GROUND_SAMPLE_MAX_ABS_HEIGHT_M): high ground in * tests the vertical from 0 to GROUND_SAMPLE_MAX_ABS_HEIGHT_M, every height a
* view is never mistaken for an unseen base. Unseen ground is sampled on the * sample can accept, so high ground in view is never mistaken for an unseen
* first walk that sees it. * base. Unseen ground is sampled on the first walk that sees it.
*/ */
function groundSampleInView(viewer, record) { function groundSampleInView(viewer, record) {
const camera = viewer.camera; const camera = viewer.camera;
@@ -1162,37 +1170,36 @@ function groundSampleInView(viewer, record) {
const known = const known =
Number.isFinite(terrain) && Number.isFinite(terrain) &&
Math.abs(terrain) <= GROUND_SAMPLE_MAX_ABS_HEIGHT_M; Math.abs(terrain) <= GROUND_SAMPLE_MAX_ABS_HEIGHT_M;
const span = GROUND_SAMPLE_MAX_ABS_HEIGHT_M / 2; const low = groundSamplePoint(record, known ? terrain : 0, groundSampleLow);
groundSampleCarto.longitude = record.carto.longitude; const high = known
groundSampleCarto.latitude = record.carto.latitude; ? low
groundSampleCarto.height = known ? terrain : span; : groundSamplePoint(
Cesium.Cartographic.toCartesian( record,
groundSampleCarto, GROUND_SAMPLE_MAX_ABS_HEIGHT_M,
Cesium.Ellipsoid.WGS84, groundSampleHigh,
groundSampleSphere.center,
); );
groundSampleSphere.radius = known ? 1 : span; // The vertical is unseen only when both ends are outside the same plane.
const culling = camera.frustum.computeCullingVolume( const { planes } = camera.frustum.computeCullingVolume(
camera.positionWC, camera.positionWC,
camera.directionWC, camera.directionWC,
camera.upWC, camera.upWC,
); );
for (const plane of planes) {
if ( if (
culling.computeVisibility(groundSampleSphere) === Cesium.Intersect.OUTSIDE Cesium.Cartesian3.dot(plane, low) + plane.w < 0 &&
Cesium.Cartesian3.dot(plane, high) + plane.w < 0
) )
return false; return false;
// The highest ground the sample could find is the last to drop below the }
// horizon. // The ellipsoidal occluder hides every point below the ellipsoid from a
if (!known) groundSampleCarto.height = GROUND_SAMPLE_MAX_ABS_HEIGHT_M; // camera near it, so ground below 0 m (low-geoid coasts, the Dead Sea) is
// tested at 0 m; unknown ground at the top of the vertical.
const horizonHeight = known
? Math.max(terrain, 0)
: GROUND_SAMPLE_MAX_ABS_HEIGHT_M;
groundSampleOccluder.cameraPosition = camera.positionWC; groundSampleOccluder.cameraPosition = camera.positionWC;
return groundSampleOccluder.isPointVisible( return groundSampleOccluder.isPointVisible(
known groundSamplePoint(record, horizonHeight, groundSampleHigh),
? groundSampleSphere.center
: Cesium.Cartographic.toCartesian(
groundSampleCarto,
Cesium.Ellipsoid.WGS84,
groundSampleTop,
),
); );
} }