mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 02:44:02 +00:00
fix(street-level): IC8 review of the Street View provider
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]>
This commit is contained in:
1 parent
22b0009138
commit
7bfcf177ac
35 files changed
+1108
-388
No files matched your search
@@ -1,84 +1,127 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import * as Cesium from 'cesium';
|
||||
import { createGroundClick } from './groundClick.js';
|
||||
import { isPickedWorldPosition } from '../../data/scenePick.js';
|
||||
import { createGroundClick, groundClickHeightOk } from './groundClick.js';
|
||||
import * as scenePick from '../../data/scenePick.js';
|
||||
|
||||
const GROUND = Cesium.Cartesian3.fromDegrees(-121.4944, 38.5816, 10);
|
||||
const TILESET = { isCesium3DTileset: true };
|
||||
|
||||
/** A layer state with providers `{id, on, groundClick, configured}` and a camera `height` m up. */
|
||||
/**
|
||||
* A layer state with providers `{id, on, groundClick, configured, available}`;
|
||||
* `picked` is where the depth buffer lands, `ellipsoid` the fallback hit.
|
||||
*/
|
||||
function harness({
|
||||
providers = [
|
||||
{ id: 'mapillary', groundClick: false },
|
||||
{ id: 'google', groundClick: true },
|
||||
],
|
||||
height = 400,
|
||||
ready = true,
|
||||
enabled = true,
|
||||
picked = GROUND,
|
||||
ellipsoid = undefined,
|
||||
} = {}) {
|
||||
const opened = [];
|
||||
const state = {
|
||||
enabled,
|
||||
services: { scenePick: { isPickedWorldPosition } },
|
||||
groundClickReady: ready,
|
||||
services: { scenePick },
|
||||
providers: new Map(
|
||||
providers.map(({ id, on = true, groundClick, configured = true }) => [
|
||||
id,
|
||||
{
|
||||
on,
|
||||
def: { id, groundClick },
|
||||
status: { configured },
|
||||
},
|
||||
]),
|
||||
providers.map(
|
||||
({
|
||||
id,
|
||||
on = true,
|
||||
groundClick,
|
||||
configured = true,
|
||||
available = true,
|
||||
}) => [
|
||||
id,
|
||||
{ on, def: { id, groundClick }, status: { configured }, available },
|
||||
],
|
||||
),
|
||||
),
|
||||
viewer: {
|
||||
scene: {
|
||||
pickPositionSupported: true,
|
||||
pickPosition: () => picked,
|
||||
globe: { getHeight: () => 10 },
|
||||
},
|
||||
camera: {
|
||||
positionCartographic: Cesium.Cartographic.fromDegrees(
|
||||
-121.4944,
|
||||
38.5816,
|
||||
10 + height,
|
||||
),
|
||||
pickEllipsoid: () => undefined,
|
||||
},
|
||||
scene: { pickPositionSupported: true, pickPosition: () => picked },
|
||||
camera: { pickEllipsoid: () => ellipsoid },
|
||||
},
|
||||
};
|
||||
const openAtGround = createGroundClick({
|
||||
state,
|
||||
parts: {},
|
||||
openNearest: (point, options) => {
|
||||
opened.push({ point, options });
|
||||
return Promise.resolve(true);
|
||||
},
|
||||
isAvailable: (entry) => entry.available,
|
||||
});
|
||||
return { state, opened, openAtGround };
|
||||
return { opened, openAtGround };
|
||||
}
|
||||
|
||||
test('a ground click at street zoom opens the nearest image of the click-to-open providers there', () => {
|
||||
const { opened, openAtGround } = harness();
|
||||
openAtGround({ x: 10, y: 20 });
|
||||
assert.equal(opened.length, 1);
|
||||
const [{ point, options }] = opened;
|
||||
assert.ok(Math.abs(point.lon - -121.4944) < 1e-9);
|
||||
assert.ok(Math.abs(point.lat - 38.5816) < 1e-9);
|
||||
assert.deepEqual(options, { providerIds: ['google'] });
|
||||
});
|
||||
const near = (point) =>
|
||||
Math.abs(point.lon - -121.4944) < 1e-9 &&
|
||||
Math.abs(point.lat - 38.5816) < 1e-9;
|
||||
|
||||
test('nothing opens from high up, over the sky, with the provider off or unconfigured, or the layer off', () => {
|
||||
for (const options of [
|
||||
{ height: 5000 },
|
||||
{ picked: null },
|
||||
{ picked: new Cesium.Cartesian3(500, 0, 0) },
|
||||
{ providers: [{ id: 'google', groundClick: true, on: false }] },
|
||||
{ providers: [{ id: 'google', groundClick: true, configured: false }] },
|
||||
{ providers: [{ id: 'mapillary', groundClick: false }] },
|
||||
{ enabled: false },
|
||||
]) {
|
||||
const { opened, openAtGround } = harness(options);
|
||||
assert.equal(openAtGround({ x: 1, y: 1 }), false, JSON.stringify(options));
|
||||
assert.equal(opened.length, 0);
|
||||
test('a click on the map opens the click-to-open providers there, without moving the camera', () => {
|
||||
for (const picked of [undefined, { primitive: TILESET }, { content: {} }]) {
|
||||
const { opened, openAtGround } = harness();
|
||||
openAtGround({ x: 10, y: 20 }, picked);
|
||||
assert.equal(opened.length, 1, JSON.stringify(picked));
|
||||
assert.ok(near(opened[0].point));
|
||||
assert.deepEqual(opened[0].options, {
|
||||
providerIds: ['google'],
|
||||
frame: false,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
test('where the depth buffer names no place, the ellipsoid answers', () => {
|
||||
const { opened, openAtGround } = harness({
|
||||
picked: new Cesium.Cartesian3(500, 0, 0),
|
||||
ellipsoid: GROUND,
|
||||
});
|
||||
openAtGround({ x: 1, y: 1 });
|
||||
assert.ok(near(opened[0].point));
|
||||
});
|
||||
|
||||
test('nothing opens over another layer’s object, the sky, from high up, off its map stack, or with the provider off', () => {
|
||||
const cases = [
|
||||
{ picked: { id: { id: 'flight:1' } }, label: 'an entity' },
|
||||
{ picked: { id: 'cctv:7', primitive: TILESET }, label: 'an id on a tile' },
|
||||
{ options: { picked: null, ellipsoid: undefined }, label: 'the sky' },
|
||||
{ options: { ready: false }, label: 'high up' },
|
||||
{
|
||||
options: {
|
||||
providers: [{ id: 'google', groundClick: true, available: false }],
|
||||
},
|
||||
label: 'not Google 3D',
|
||||
},
|
||||
{
|
||||
options: { providers: [{ id: 'google', groundClick: true, on: false }] },
|
||||
label: 'off',
|
||||
},
|
||||
{
|
||||
options: {
|
||||
providers: [{ id: 'google', groundClick: true, configured: false }],
|
||||
},
|
||||
label: 'no key',
|
||||
},
|
||||
{ options: { enabled: false }, label: 'layer off' },
|
||||
];
|
||||
for (const { picked, options = {}, label } of cases) {
|
||||
const { opened, openAtGround } = harness(options);
|
||||
assert.equal(openAtGround({ x: 1, y: 1 }, picked), false, label);
|
||||
assert.equal(opened.length, 0, label);
|
||||
}
|
||||
});
|
||||
|
||||
test('street zoom is measured above the ground under the camera', () => {
|
||||
const viewer = (height) => ({
|
||||
camera: {
|
||||
positionCartographic: Cesium.Cartographic.fromDegrees(0, 0, height),
|
||||
},
|
||||
scene: { globe: { getHeight: () => 1500 } },
|
||||
});
|
||||
// 1,500 m up a plateau, 2,000 m above it: still a street.
|
||||
assert.equal(groundClickHeightOk(viewer(3500)), true);
|
||||
assert.equal(groundClickHeightOk(viewer(5000)), false);
|
||||
assert.equal(groundClickHeightOk(null), false);
|
||||
});
|
||||
Reference in new issue
Block a user