fix(infrastructure): test the ground, not the ellipsoid, for in-view sampling

An unsampled base sits at ellipsoid height 0. Over high terrain seen at an
angle that point projects below the screen while the ground above it is in
view, so the gate skipped ground the camera could see and never sampled it.
The gate now tests loaded globe terrain when there is some, and otherwise
the whole span of heights a sample can accept (0 to 9,000 m).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
quanticsoul4772andClaude Opus 5.5 committed 2026-10-29 01:25:57 -07:00
1 parent 189b30b545
commit ecc0ced47c
4 files changed
+106 -15

No files matched your search

@@ -1,4 +1,4 @@
- Ground-sample Data Centers and Dams markers only when the camera sees their
base. An off-screen base read through the Earth and retried every 2 s, which
held the page near 2 s a frame over Ashburn, Virginia on the Esri map
- Ground-sample Data Centers and Dams markers only when the camera sees the
ground under them. Unseen ground read through the Earth and retried every
2 s; over Ashburn, Virginia on the Esri map, slow frames reached 2 s
(quanticsoul4772, #1464).
+5 -3
View File
@@ -1959,9 +1959,11 @@ 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 base is in the
camera's view and above the horizon (an unseen base reads through the Earth
and would retry every 2 s), and uses valid loaded terrain as a floor while
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
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
+58
View File
@@ -787,6 +787,64 @@ 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 }],
]) {
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.
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 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');
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);
});
}
test('settled terrain refinement lifts an already sampled stem without another GPU sample', async (t) => {
const env = await createRealLocalLayerHarness({
sampleHeightSupported: true, sampleHeight: () => 117,
+40 -9
View File
@@ -1140,29 +1140,60 @@ const groundSampleOccluder = new Cesium.EllipsoidalOccluder(
Cesium.Ellipsoid.WGS84,
);
const groundSampleCarto = new Cesium.Cartographic();
const groundSampleTop = new Cesium.Cartesian3();
/**
* Whether the camera sees the record's base: inside the view frustum and
* above the horizon. scene.sampleHeight reads only surface rendered for the
* current view, so a sample of an unseen base passes through 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 the page near 2 s
* a frame indefinitely. An unseen base keeps its stem at the unsampled height
* and is sampled on the first walk that sees it.
* Whether the camera can see the ground under the record: inside the view
* frustum and above the horizon. scene.sampleHeight reads only surface
* rendered for the current view, so a sample of unseen ground passes through
* 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.
*/
function groundSampleInView(viewer, record) {
const camera = viewer.camera;
const globe = viewer.scene.globe;
const terrain = globe?.show ? globe.getHeight?.(record.carto) : undefined;
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(
camera.positionWC,
camera.directionWC,
camera.upWC,
);
Cesium.Cartesian3.clone(record.base, groundSampleSphere.center);
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;
groundSampleOccluder.cameraPosition = camera.positionWC;
return groundSampleOccluder.isPointVisible(record.base);
return groundSampleOccluder.isPointVisible(
known
? groundSampleSphere.center
: Cesium.Cartographic.toCartesian(
groundSampleCarto,
Cesium.Ellipsoid.WGS84,
groundSampleTop,
),
);
}
function sampleLocalGroundHeight(viewer, record, now) {