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
+130 -86

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.
Unchanged overlay entries do not request another frame; moved positions,
changed membership and re-enabling still publish. Ground sampling waits for
visible globe tiles to settle, samples only markers whose ground is in the
camera's view and above the horizon (unseen ground reads through the Earth
and would retry every 2 s; until it is seen, a stem keeps its unsampled
height, which can show for a stem whose base is just off screen), and uses
valid loaded terrain as a floor while
visible globe tiles to settle, and skips markers whose ground the camera
cannot see (unseen ground reads through the Earth and would retry every 2 s).
Ground is tested at loaded globe terrain, or across 0-9,000 m when the globe
is hidden, so photoreal views skip only ground well out of view. Until it is
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
constrain photoreal geometry, and retry work remains bounded. Already sampled
nearby markers follow higher settled terrain on existing bounded walks, without
+82 -46
View File
@@ -113,8 +113,13 @@ async function createRealLocalLayerHarness({
upWC: new Cesium.Cartesian3(),
frustum: {
fov: Math.PI / 3,
// No planes: everything is in view. One plane no point satisfies:
// nothing is.
computeCullingVolume: () => ({
computeVisibility: () => baseVisibility,
planes:
baseVisibility === Cesium.Intersect.OUTSIDE
? [new Cesium.Cartesian4(0, 0, 0, -1)]
: [],
}),
},
moveEnd,
@@ -787,64 +792,95 @@ 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);
});
for (const [label, globe] of [
['loaded terrain', { show: true, tilesLoaded: true, getHeight: () => 2_500 }],
['a hidden globe', { show: false, tilesLoaded: true, getHeight: () => undefined }],
/**
* Give the harness a real Cesium camera `southM` metres south of the base at
* `cameraM` metres above the ellipsoid, looking at the base's ground at
* `groundM` (or directly away from it).
*/
function aimRealCamera(env, { groundM, cameraM, southM, away = false }) {
const entity = env.dataSources[0].entities.values[0];
const base = Cesium.Cartographic.fromCartesian(entity.__localBaseCartesian);
const ground = Cesium.Cartesian3.fromRadians(base.longitude, base.latitude, groundM);
const position = Cesium.Cartesian3.fromRadians(
base.longitude,
base.latitude - southM / 6_371_000,
cameraM,
);
const direction = Cesium.Cartesian3.normalize(
away
? Cesium.Cartesian3.subtract(position, ground, new Cesium.Cartesian3())
: Cesium.Cartesian3.subtract(ground, position, new Cesium.Cartesian3()),
new Cesium.Cartesian3(),
);
const right = Cesium.Cartesian3.normalize(
Cesium.Cartesian3.cross(
direction,
Cesium.Ellipsoid.WGS84.geodeticSurfaceNormal(position),
new Cesium.Cartesian3(),
),
new Cesium.Cartesian3(),
);
const up = Cesium.Cartesian3.cross(right, direction, new Cesium.Cartesian3());
const frustum = new Cesium.PerspectiveFrustum({
fov: Math.PI / 3,
aspectRatio: 800 / 600,
near: 1,
far: 1e8,
});
Object.assign(env.viewer.camera, {
positionWC: position,
directionWC: direction,
upWC: up,
frustum,
});
return frustum
.computeCullingVolume(position, direction, up)
.computeVisibility(new Cesium.BoundingSphere(entity.__localBaseCartesian, 1));
}
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(`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
// ellipsoid-height point is far below the bottom of the screen.
test(`${label} in view is sampled`, async (t) => {
const env = await createRealLocalLayerHarness({
sampleHeightSupported: true, sampleHeight: () => 2_500,
sampleHeightSupported: true, sampleHeight: () => groundM,
});
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 base = Cesium.Cartographic.fromCartesian(entity.__localBaseCartesian);
const ground = Cesium.Cartesian3.fromRadians(base.longitude, base.latitude, 2_500);
const position = Cesium.Cartesian3.fromRadians(
base.longitude,
base.latitude - 3_000 / 6_371_000,
2_500 + 1_000,
);
const direction = Cesium.Cartesian3.normalize(
Cesium.Cartesian3.subtract(ground, position, new Cesium.Cartesian3()),
new Cesium.Cartesian3(),
);
const right = Cesium.Cartesian3.normalize(
Cesium.Cartesian3.cross(
direction,
Cesium.Ellipsoid.WGS84.geodeticSurfaceNormal(position),
new Cesium.Cartesian3(),
),
new Cesium.Cartesian3(),
);
const up = Cesium.Cartesian3.cross(right, direction, new Cesium.Cartesian3());
const frustum = new Cesium.PerspectiveFrustum({
fov: Math.PI / 3,
aspectRatio: 800 / 600,
near: 1,
far: 1e8,
});
Object.assign(env.viewer.camera, {
positionWC: position,
directionWC: direction,
upWC: up,
frustum,
});
const offScreen = frustum
.computeCullingVolume(position, direction, up)
.computeVisibility(new Cesium.BoundingSphere(entity.__localBaseCartesian, 1));
assert.equal(offScreen, Cesium.Intersect.OUTSIDE, 'precondition: the ellipsoid-height base is off screen');
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);
env.preRender.raise();
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) => {
const env = await createRealLocalLayerHarness({
sampleHeightSupported: true, sampleHeight: () => 117,
+42 -35
View File
@@ -1131,17 +1131,25 @@ function refreshLocalTerrainFloor(viewer, record) {
return true;
}
const groundSampleSphere = new Cesium.BoundingSphere(
new Cesium.Cartesian3(),
1,
);
const groundSampleOccluder = new Cesium.EllipsoidalOccluder(
Cesium.Ellipsoid.WGS84,
);
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
@@ -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
* 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
* uses loaded globe terrain when there is some, and otherwise every height a
* sample can accept (0 to GROUND_SAMPLE_MAX_ABS_HEIGHT_M): high ground in
* view is never mistaken for an unseen base. Unseen ground is sampled on the
* first walk that sees it.
* uses loaded globe terrain when there is some. Otherwise (a hidden globe) it
* tests the vertical from 0 to GROUND_SAMPLE_MAX_ABS_HEIGHT_M, every height a
* sample can accept, so high ground in view is never mistaken for an unseen
* base. Unseen ground is sampled on the first walk that sees it.
*/
function groundSampleInView(viewer, record) {
const camera = viewer.camera;
@@ -1162,37 +1170,36 @@ function groundSampleInView(viewer, record) {
const known =
Number.isFinite(terrain) &&
Math.abs(terrain) <= GROUND_SAMPLE_MAX_ABS_HEIGHT_M;
const span = GROUND_SAMPLE_MAX_ABS_HEIGHT_M / 2;
groundSampleCarto.longitude = record.carto.longitude;
groundSampleCarto.latitude = record.carto.latitude;
groundSampleCarto.height = known ? terrain : span;
Cesium.Cartographic.toCartesian(
groundSampleCarto,
Cesium.Ellipsoid.WGS84,
groundSampleSphere.center,
);
groundSampleSphere.radius = known ? 1 : span;
const culling = camera.frustum.computeCullingVolume(
const low = groundSamplePoint(record, known ? terrain : 0, groundSampleLow);
const high = known
? low
: groundSamplePoint(
record,
GROUND_SAMPLE_MAX_ABS_HEIGHT_M,
groundSampleHigh,
);
// The vertical is unseen only when both ends are outside the same plane.
const { planes } = camera.frustum.computeCullingVolume(
camera.positionWC,
camera.directionWC,
camera.upWC,
);
if (
culling.computeVisibility(groundSampleSphere) === Cesium.Intersect.OUTSIDE
)
return false;
// The highest ground the sample could find is the last to drop below the
// horizon.
if (!known) groundSampleCarto.height = GROUND_SAMPLE_MAX_ABS_HEIGHT_M;
for (const plane of planes) {
if (
Cesium.Cartesian3.dot(plane, low) + plane.w < 0 &&
Cesium.Cartesian3.dot(plane, high) + plane.w < 0
)
return false;
}
// The ellipsoidal occluder hides every point below the ellipsoid from a
// 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;
return groundSampleOccluder.isPointVisible(
known
? groundSampleSphere.center
: Cesium.Cartographic.toCartesian(
groundSampleCarto,
Cesium.Ellipsoid.WGS84,
groundSampleTop,
),
groundSamplePoint(record, horizonHeight, groundSampleHigh),
);
}