mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 10:24:02 +00:00
Google's Maps Platform terms forbid Street View imagery beside non-Google maps, so the provider declares requiresMapStack: 'photoreal': off Google 3D its chip is dashed with the reason, lookups and opens skip it, and leaving Google 3D closes its panorama. - Ground clicks: only a click on the map itself (scenePick.isSurfacePick: nothing picked or Google 3D tile content) at street zoom opens Street View, and the camera stays put; higher up the hint says to zoom in. scenePick.pickGroundPosition replaces the copy in Directions. - Viewer: poses go out at once and again when the date and address arrive, so an open never hangs on that lookup; one lookup per panorama, seeded by the nearest lookup; a close settles a pending open; failed lookups are asked again; poses follow position changes, not pano_changed. - Loader: the gm_authFailure handler is installed once, so a retried load reports a refusal once. - Viewer host: a prewarm that lands after another provider took the host is released; FIT/FILL availability is set on every open. - Provider: a refusal while switched off reports no error over another photo; SINCE compares against the end of Google's month; messages name the referrer and network causes; FLAT says Street View is 360° only. - The layer row names the key of the providers that are on; the MCP panel CSP admits Street View's tiles, control images and photos. - Tests for each, against fakes that now follow Google's event order; the browser gate restores its state, waits instead of sleeping, aims its panel clicks and corner drags, and asserts the camera stays put. Co-Authored-By: Claude Opus 5.5 <[email protected]>
187 lines
7.4 KiB
JavaScript
187 lines
7.4 KiB
JavaScript
import { test } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import * as Cesium from 'cesium';
|
|
import { isPickedWorldPosition } from './scenePick.js';
|
|
|
|
const describe = (position) =>
|
|
position ? `(${position.x}, ${position.y}, ${position.z})` : String(position);
|
|
|
|
test('a degenerate depth pick is rejected before it reaches Cesium', () => {
|
|
// These are the shapes `scene.pickPosition()` can produce when the depth read
|
|
// over empty sky is meaningless. Each one is a MISSED pick, not a place.
|
|
const degenerate = [
|
|
null,
|
|
undefined,
|
|
new Cesium.Cartesian3(Number.NaN, Number.NaN, Number.NaN),
|
|
new Cesium.Cartesian3(0, 0, 0),
|
|
new Cesium.Cartesian3(Number.POSITIVE_INFINITY, 0, 0),
|
|
new Cesium.Cartesian3(0, Number.NEGATIVE_INFINITY, 0),
|
|
new Cesium.Cartesian3(1, Number.NaN, 1),
|
|
new Cesium.Cartesian3(0.2, -0.3, 0.1),
|
|
];
|
|
for (const position of degenerate) {
|
|
assert.equal(
|
|
isPickedWorldPosition(position),
|
|
false,
|
|
`must reject ${describe(position)}`,
|
|
);
|
|
}
|
|
});
|
|
|
|
test('the guard is an Earth-sized band, not just a non-zero check', () => {
|
|
// Finiteness alone is not validation. A pick has to land in the shell the
|
|
// Earth actually occupies, because the values BETWEEN "zero" and "the globe"
|
|
// are the ones that fail quietly.
|
|
const belowTheFloor = [
|
|
// The adversarial probe: finite, non-zero, and 6,378 km underground. A bare
|
|
// non-zero check accepts it, and the shipped path then reverse-geocodes
|
|
// 0°, 0° as if the operator were looking at the Gulf of Guinea.
|
|
new Cesium.Cartesian3(500, 0, 0),
|
|
new Cesium.Cartesian3(0, 1_000_000, 0),
|
|
new Cesium.Cartesian3(0, 0, 5_999_999),
|
|
];
|
|
for (const position of belowTheFloor) {
|
|
assert.equal(
|
|
isPickedWorldPosition(position),
|
|
false,
|
|
`must reject ${describe(position)}`,
|
|
);
|
|
// Each one converts WITHOUT throwing — that is exactly what makes it dangerous.
|
|
const carto = Cesium.Cartographic.fromCartesian(position);
|
|
assert.ok(carto, `Cesium converts ${describe(position)} without complaint`);
|
|
assert.ok(
|
|
carto.height < -300_000,
|
|
'and puts the "target" hundreds of km underground',
|
|
);
|
|
}
|
|
|
|
const aboveTheCeiling = [
|
|
new Cesium.Cartesian3(1_000_000_001, 0, 0),
|
|
new Cesium.Cartesian3(0, 1e12, 0),
|
|
// Large enough to overflow Cesium's geodetic iteration into NaN.
|
|
new Cesium.Cartesian3(1e155, 0, 0),
|
|
];
|
|
for (const position of aboveTheCeiling) {
|
|
assert.equal(
|
|
isPickedWorldPosition(position),
|
|
false,
|
|
`must reject ${describe(position)}`,
|
|
);
|
|
}
|
|
assert.throws(
|
|
() => Cesium.Cartographic.fromCartesian(new Cesium.Cartesian3(1e155, 0, 0)),
|
|
/normalized result is not a number/,
|
|
'the ceiling is load-bearing: an absurd finite magnitude still throws',
|
|
);
|
|
|
|
// Both edges of the band are inclusive, and both are real magnitudes.
|
|
assert.equal(
|
|
isPickedWorldPosition(new Cesium.Cartesian3(6_000_000, 0, 0)),
|
|
true,
|
|
);
|
|
assert.equal(
|
|
isPickedWorldPosition(new Cesium.Cartesian3(1_000_000_000, 0, 0)),
|
|
true,
|
|
);
|
|
});
|
|
|
|
test('a real picked position is accepted', () => {
|
|
const real = [
|
|
// Ground, a cruising airliner, and the deepest surface point on the globe.
|
|
Cesium.Cartesian3.fromDegrees(-97.7431, 30.2672, 0),
|
|
Cesium.Cartesian3.fromDegrees(139.6917, 35.6895, 12_000),
|
|
Cesium.Cartesian3.fromDegrees(0, -89.9, -400),
|
|
Cesium.Cartesian3.fromDegrees(142.2, 11.35, -10_935),
|
|
// A tall structure: pickPosition returns the mesh, not the terrain.
|
|
Cesium.Cartesian3.fromDegrees(55.2744, 25.1972, 828),
|
|
// The polar surface is the smallest magnitude the globe can produce.
|
|
Cesium.Cartesian3.fromDegrees(0, 90, 0),
|
|
// Satellites are real contacts too, up to geostationary.
|
|
Cesium.Cartesian3.fromDegrees(0, 0, 550_000),
|
|
Cesium.Cartesian3.fromDegrees(0, 0, 35_786_000),
|
|
];
|
|
for (const position of real) {
|
|
assert.equal(
|
|
isPickedWorldPosition(position),
|
|
true,
|
|
`must accept ${describe(position)}`,
|
|
);
|
|
}
|
|
|
|
// The floor has real margin under the smallest legitimate magnitude, so no
|
|
// plausible pick sits anywhere near the boundary.
|
|
const polarSurface = Cesium.Cartesian3.magnitude(
|
|
Cesium.Cartesian3.fromDegrees(0, 90, -10_935),
|
|
);
|
|
assert.ok(
|
|
polarSurface > 6_300_000,
|
|
`smallest real magnitude was ${polarSurface}`,
|
|
);
|
|
});
|
|
|
|
test('the guard rejects each way Cesium mishandles a degenerate pick', () => {
|
|
// This pins the REASON for the guard, so it cannot drift into cargo cult.
|
|
// Cesium fails three different ways, and only one of them is loud.
|
|
|
|
// 1. Non-finite components throw — the uncaught DeveloperError on the demo path.
|
|
for (const position of [
|
|
new Cesium.Cartesian3(Number.NaN, Number.NaN, Number.NaN),
|
|
new Cesium.Cartesian3(Number.POSITIVE_INFINITY, 0, 0),
|
|
new Cesium.Cartesian3(1, Number.NaN, 1),
|
|
]) {
|
|
assert.throws(
|
|
() => Cesium.Cartographic.fromCartesian(position),
|
|
/normalized result is not a number/,
|
|
`Cesium must still throw on ${describe(position)}`,
|
|
);
|
|
assert.equal(isPickedWorldPosition(position), false);
|
|
}
|
|
|
|
// 2. Exactly the center returns undefined — silent, and a TypeError at any
|
|
// call site that reads `.latitude` off the result.
|
|
const center = new Cesium.Cartesian3(0, 0, 0);
|
|
assert.equal(Cesium.Cartographic.fromCartesian(center), undefined);
|
|
assert.equal(isPickedWorldPosition(center), false);
|
|
|
|
// 3. A near-center point converts "successfully" into a place inside the
|
|
// Earth's core. That is the quietest failure of the three and the reason
|
|
// the guard needs a magnitude band, not just a finiteness check.
|
|
const nearCenter = new Cesium.Cartesian3(0.2, -0.3, 0.1);
|
|
assert.ok(
|
|
Cesium.Cartographic.fromCartesian(nearCenter),
|
|
'Cesium converts it without complaint',
|
|
);
|
|
assert.equal(isPickedWorldPosition(nearCenter), false);
|
|
|
|
// …and every position the guard accepts must convert to the right place.
|
|
const accepted = Cesium.Cartesian3.fromDegrees(-97.7431, 30.2672, 250);
|
|
assert.equal(isPickedWorldPosition(accepted), true);
|
|
const carto = Cesium.Cartographic.fromCartesian(accepted);
|
|
assert.ok(carto, 'a valid pick must convert');
|
|
assert.ok(Math.abs(Cesium.Math.toDegrees(carto.longitude) + 97.7431) < 1e-6);
|
|
assert.ok(Math.abs(Cesium.Math.toDegrees(carto.latitude) - 30.2672) < 1e-6);
|
|
});
|
|
|
|
test('the ground under a click: the rendered surface, else the ellipsoid, never the sky', async () => {
|
|
const { pickGroundPosition } = await import('./scenePick.js');
|
|
const ground = { x: 6378137, y: 0, z: 0 };
|
|
const sky = { x: 500, y: 0, z: 0 };
|
|
const viewer = (picked, ellipsoid) => ({
|
|
scene: { pickPositionSupported: true, pickPosition: () => picked },
|
|
camera: { pickEllipsoid: () => ellipsoid },
|
|
});
|
|
assert.equal(pickGroundPosition(viewer(ground, null), {}), ground);
|
|
assert.equal(pickGroundPosition(viewer(sky, ground), {}), ground);
|
|
assert.equal(pickGroundPosition(viewer(undefined, undefined), {}), null);
|
|
assert.equal(pickGroundPosition(null, {}), null);
|
|
});
|
|
|
|
test('a surface pick is nothing, or Google 3D tile content without an id', async () => {
|
|
const { isSurfacePick } = await import('./scenePick.js');
|
|
assert.equal(isSurfacePick(undefined), true);
|
|
assert.equal(isSurfacePick({ content: {} }), true);
|
|
assert.equal(isSurfacePick({ primitive: { isCesium3DTileset: true } }), true);
|
|
assert.equal(isSurfacePick({ id: 'flight:1', content: {} }), false);
|
|
assert.equal(isSurfacePick({ primitive: {} }), false, 'an unnamed primitive');
|
|
});
|