mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-06 19:34:01 +00:00
test(globe): pick round-trip and setTerrain checks in the contract suite
Two engine-neutral checks: pickPosition then worldToWindow lands within 1.5 px of the screen point (over New York, straight down and tilted; points with no surface are skipped, at least one must hit), and maps.setTerrain resolves for keyless terrain and rejects an unknown kind. The fake engine now rejects unknown terrain kinds, as both engines do. The Navara contract page shows OSM on keyless terrain before the suite, since depth picks need a drawn surface.
This commit is contained in:
1 parent
b65dbab709
commit
312ed416e9
2 files changed
+81
No files matched your search
@@ -1417,6 +1417,78 @@ export function createContractSuite(
|
||||
);
|
||||
},
|
||||
],
|
||||
[
|
||||
'picker.pickPosition and projector.worldToWindow round-trip within 1.5 px',
|
||||
async () => {
|
||||
if (!engine.picker.pickPositionSupported) return;
|
||||
// Straight down and tilted; screen points with no surface are skipped.
|
||||
// Over New York, low enough for map detail.
|
||||
const views = [
|
||||
{ height: 20000, heading: 0, pitch: -math.PI_OVER_TWO },
|
||||
{ height: 5000, heading: 0.7, pitch: -1.0 },
|
||||
];
|
||||
let hits = 0;
|
||||
const misses = [];
|
||||
for (const { height: viewHeight, heading, pitch } of views) {
|
||||
camera.setView({
|
||||
destination: cartesian3.fromDegrees(-73.78, 40.64, viewHeight),
|
||||
orientation: { heading, pitch, roll: 0 },
|
||||
});
|
||||
// Picks read the depth of the last drawn frame: draw this view.
|
||||
await settle(3);
|
||||
const { width, height } = engine.host.size();
|
||||
const screens = [
|
||||
[0.5, 0.5],
|
||||
[0.3, 0.4],
|
||||
[0.7, 0.6],
|
||||
[0.5, 0.75],
|
||||
].map(([x, y]) =>
|
||||
cartesian2.create(Math.round(width * x), Math.round(height * y)),
|
||||
);
|
||||
// The depth a pick reads needs drawn frames.
|
||||
await until(
|
||||
() => engine.picker.pickPosition(screens[0]) !== undefined,
|
||||
'a surface under the centre for pickPosition',
|
||||
);
|
||||
for (const screen of screens) {
|
||||
const position = engine.picker.pickPosition(screen);
|
||||
if (position === undefined) continue;
|
||||
const back = engine.projector.worldToWindow(position);
|
||||
const error = back
|
||||
? Math.hypot(back.x - screen.x, back.y - screen.y)
|
||||
: Infinity;
|
||||
hits += 1;
|
||||
if (!(error <= 1.5))
|
||||
misses.push(
|
||||
`(${screen.x}, ${screen.y}) → ${back ? `(${back.x.toFixed(2)}, ${back.y.toFixed(2)})` : 'undefined'}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
ensure(hits > 0, 'pickPosition hit no surface');
|
||||
ensure(
|
||||
misses.length === 0,
|
||||
`round-trip off by more than 1.5 px: ${misses.join('; ')}`,
|
||||
);
|
||||
},
|
||||
],
|
||||
[
|
||||
'maps.setTerrain: keyless terrain resolves; an unknown kind rejects',
|
||||
async () => {
|
||||
await engine.maps.setTerrain({ id: 'keyless', kind: 'keyless' });
|
||||
let rejected = null;
|
||||
try {
|
||||
await engine.maps.setTerrain({
|
||||
id: 'no-such-terrain',
|
||||
kind: 'no-such-terrain',
|
||||
});
|
||||
} catch (error) {
|
||||
rejected = error;
|
||||
}
|
||||
ensure(rejected !== null, 'an unknown terrain kind resolved');
|
||||
// The keyless terrain still applies after the rejection.
|
||||
await engine.maps.setTerrain({ id: 'keyless', kind: 'keyless' });
|
||||
},
|
||||
],
|
||||
[
|
||||
'camera.commanded: fires for each camera command, never for reads',
|
||||
async () => {
|
||||
|
||||
@@ -24,6 +24,8 @@ const { cartesian2, cartesian3, cartographic, ellipsoid, math, matrix4 } = geo;
|
||||
const WGS84 = ellipsoid.WGS84;
|
||||
const RADII = WGS84.radii;
|
||||
const MAXIMUM_RADIUS = Math.max(RADII.x, RADII.y, RADII.z);
|
||||
// The terrain kinds the engines build themselves (src/maps/registry.js).
|
||||
const TERRAIN_KINDS = Object.freeze(['ellipsoid', 'keyless', 'world']);
|
||||
const DEFAULT_FLIGHT_SECONDS = 3;
|
||||
const DEFAULT_ZOOM_AMOUNT = 100000; // Cesium's camera.defaultZoomAmount
|
||||
const ZERO_RADIUS_SPHERE_RANGE = 100; // Cesium's MINIMUM_ZOOM
|
||||
@@ -845,6 +847,13 @@ export function createFakeEngine(options = {}) {
|
||||
},
|
||||
async setTerrain(source) {
|
||||
record('maps.setTerrain', [source]);
|
||||
// As the real engines: a prebuilt source or a known kind.
|
||||
const kind = source?.kind ?? source?.id;
|
||||
if (
|
||||
typeof source?.create !== 'function' &&
|
||||
!TERRAIN_KINDS.includes(kind)
|
||||
)
|
||||
throw new TypeError(`Unknown terrain source: ${kind}`);
|
||||
fake.maps.terrain = source;
|
||||
},
|
||||
async setPhotorealTiles(source) {
|
||||
|
||||
Reference in new issue
Block a user