mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 19:04:02 +00:00
fix(street-level): read the older {zoom, kind} zoomFor shape (#1288)
Restore legacy provider zoomFor compatibility and document supported return values. Contribution by @asturksever.
This commit is contained in:
1 parent
8dec9eaa10
commit
5b8e6fbc38
4 files changed
+67
-7
No files matched your search
@@ -0,0 +1,4 @@
|
|||||||
|
- A Street Level provider whose `zoomFor` still answers `{zoom, kind}`, the
|
||||||
|
shape before the core went slim, draws its lines again instead of a silent
|
||||||
|
blank; an overview level or any answer that is not a whole zoom shows the
|
||||||
|
zoom-in hint (asturksever, #1288).
|
||||||
@@ -3753,6 +3753,10 @@ disabled. With it, coverage draws as z11–14 sequence lines below 60 km; the pr
|
|||||||
tiles (12 MB → ~80 KB) and shares one upstream fetch between concurrent
|
tiles (12 MB → ~80 KB) and shares one upstream fetch between concurrent
|
||||||
requests for a tile.
|
requests for a tile.
|
||||||
|
|
||||||
|
Line coverage accepts a provider’s numeric `zoomFor` result or its legacy
|
||||||
|
`{zoom, kind}` shape. Overview levels and invalid zooms show the zoom-in hint
|
||||||
|
instead of silently requesting no tiles.
|
||||||
|
|
||||||
Coverage is z11–14 sequence lines below 60 km; above that nothing is drawn and
|
Coverage is z11–14 sequence lines below 60 km; above that nothing is drawn and
|
||||||
the panel says to zoom in. Tiles come from the visible ground within range of
|
the panel says to zoom in. Tiles come from the visible ground within range of
|
||||||
the camera, nearest first, at most 9 (the halves of a view across
|
the camera, nearest first, at most 9 (the halves of a view across
|
||||||
|
|||||||
@@ -105,6 +105,25 @@ function pointsOf(sequence) {
|
|||||||
* @property {boolean} [keepOrder] Cap a tile's lines in the order decoded (default: newest first).
|
* @property {boolean} [keepOrder] Cap a tile's lines in the order decoded (default: newest first).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The tile zoom a provider's `zoomFor` answered, or null. Providers written
|
||||||
|
* before the core went slim return `{zoom, kind}`: its zoom is read, and an
|
||||||
|
* `'overview'` level draws nothing, since nothing is drawn from orbit. Any
|
||||||
|
* other answer that is not a whole zoom draws nothing too, rather than
|
||||||
|
* asking for no tiles without a hint.
|
||||||
|
* @param {unknown} level
|
||||||
|
* @returns {number|null}
|
||||||
|
*/
|
||||||
|
export function coverageZoom(level) {
|
||||||
|
const zoom =
|
||||||
|
level && typeof level === 'object'
|
||||||
|
? level.kind === 'overview'
|
||||||
|
? null
|
||||||
|
: level.zoom
|
||||||
|
: level;
|
||||||
|
return Number.isInteger(zoom) && zoom >= 0 ? zoom : null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Camera-driven sequence lines from any XYZ line-tile source, near the
|
* Camera-driven sequence lines from any XYZ line-tile source, near the
|
||||||
* ground only, draped on terrain and 3D tiles alike. Nothing is drawn from
|
* ground only, draped on terrain and 3D tiles alike. Nothing is drawn from
|
||||||
@@ -115,8 +134,9 @@ function pointsOf(sequence) {
|
|||||||
* @param {(tile: {x: number, y: number, z: number}, init: {signal: AbortSignal}) => Promise<{sequences: Array<object>}>} options.fetchTile
|
* @param {(tile: {x: number, y: number, z: number}, init: {signal: AbortSignal}) => Promise<{sequences: Array<object>}>} options.fetchTile
|
||||||
* A decoded tile; sequences are `{id, parts, capturedAt, isPano}`. A
|
* A decoded tile; sequences are `{id, parts, capturedAt, isPano}`. A
|
||||||
* rejection may carry `keyRequired`, `keyRejected` or `retryAfterSec`.
|
* rejection may carry `keyRequired`, `keyRejected` or `retryAfterSec`.
|
||||||
* @param {(heightM: number|null) => number|null} options.zoomFor
|
* @param {(heightM: number|null) => number|{zoom: number, kind?: string}|null} options.zoomFor
|
||||||
* Tile zoom for a camera height above ground; null draws nothing.
|
* Tile zoom for a camera height above ground; null draws nothing. The
|
||||||
|
* older `{zoom, kind}` shape is still read (see `coverageZoom`).
|
||||||
* @param {{coverage: string, selected: string}} options.colors
|
* @param {{coverage: string, selected: string}} options.colors
|
||||||
* @param {string} options.pickPrefix Pick-id prefix of the lines.
|
* @param {string} options.pickPrefix Pick-id prefix of the lines.
|
||||||
* @param {string} options.renderKey Render-governor reason.
|
* @param {string} options.renderKey Render-governor reason.
|
||||||
@@ -380,7 +400,7 @@ export function createLineCoverage({
|
|||||||
const height = Number.isFinite(cameraHeight)
|
const height = Number.isFinite(cameraHeight)
|
||||||
? cameraHeight - (ground ?? 0)
|
? cameraHeight - (ground ?? 0)
|
||||||
: null;
|
: null;
|
||||||
const zoom = zoomFor(height);
|
const zoom = coverageZoom(zoomFor(height));
|
||||||
if (zoom == null) return { hint: messages.tooHigh || ZOOM_IN_HINT };
|
if (zoom == null) return { hint: messages.tooHigh || ZOOM_IN_HINT };
|
||||||
// Rays meet the ground where it really is (1,600 m up in Denver) and stop
|
// Rays meet the ground where it really is (1,600 m up in Denver) and stop
|
||||||
// short of the horizon, which would stretch the box to the world.
|
// short of the horizon, which would stretch the box to the world.
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import assert from 'node:assert/strict';
|
|||||||
import test from 'node:test';
|
import test from 'node:test';
|
||||||
import * as Cesium from 'cesium';
|
import * as Cesium from 'cesium';
|
||||||
import {
|
import {
|
||||||
|
coverageZoom,
|
||||||
createLineCoverage,
|
createLineCoverage,
|
||||||
freshCoverage,
|
freshCoverage,
|
||||||
ZOOM_IN_HINT,
|
ZOOM_IN_HINT,
|
||||||
@@ -28,7 +29,7 @@ const { maxSequences: COVERAGE_MAX_SEQUENCES, maxTiles: COVERAGE_MAX_TILES } =
|
|||||||
COVERAGE_TUNING;
|
COVERAGE_TUNING;
|
||||||
|
|
||||||
/** Line coverage as the Mapillary provider builds it, over `source`. */
|
/** Line coverage as the Mapillary provider builds it, over `source`. */
|
||||||
function createCoverage({ state, source }) {
|
function createCoverage({ state, source, zoomFor = coverageZoomForHeight }) {
|
||||||
return createLineCoverage({
|
return createLineCoverage({
|
||||||
state,
|
state,
|
||||||
fetchTile: async (tile, { signal }) =>
|
fetchTile: async (tile, { signal }) =>
|
||||||
@@ -36,7 +37,7 @@ function createCoverage({ state, source }) {
|
|||||||
await source.getTile('coverage', tile.z, tile.x, tile.y, { signal }),
|
await source.getTile('coverage', tile.z, tile.x, tile.y, { signal }),
|
||||||
tile,
|
tile,
|
||||||
),
|
),
|
||||||
zoomFor: coverageZoomForHeight,
|
zoomFor,
|
||||||
colors: COLORS,
|
colors: COLORS,
|
||||||
pickPrefix: PICK_PREFIX.sequence,
|
pickPrefix: PICK_PREFIX.sequence,
|
||||||
renderKey: 'mapillary-coverage',
|
renderKey: 'mapillary-coverage',
|
||||||
@@ -123,7 +124,7 @@ function deferredSource() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function setup() {
|
function setup({ zoomFor } = {}) {
|
||||||
const centre = tileCentre(-121.4944, 38.5816);
|
const centre = tileCentre(-121.4944, 38.5816);
|
||||||
const viewer = fakeViewer({ lon: centre.lon, lat: centre.lat, height: 900 });
|
const viewer = fakeViewer({ lon: centre.lon, lat: centre.lat, height: 900 });
|
||||||
const source = deferredSource();
|
const source = deferredSource();
|
||||||
@@ -146,7 +147,7 @@ function setup() {
|
|||||||
},
|
},
|
||||||
sequence: { selectedId: null },
|
sequence: { selectedId: null },
|
||||||
};
|
};
|
||||||
const coverage = createCoverage({ state, source });
|
const coverage = createCoverage({ state, source, zoomFor });
|
||||||
const bytes = encodeCoverageTile(centre.tile, {
|
const bytes = encodeCoverageTile(centre.tile, {
|
||||||
sequences: [
|
sequences: [
|
||||||
{
|
{
|
||||||
@@ -239,6 +240,37 @@ test('panning off a tile that is still loading stops counting it as loading', as
|
|||||||
coverage.clear();
|
coverage.clear();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('a zoomFor in the older {zoom, kind} shape still draws its lines', async () => {
|
||||||
|
// Providers written before the core went slim (#1139's Vegbilder) answer
|
||||||
|
// an object: it must not ask for no tiles and say nothing.
|
||||||
|
const { viewer, source, coverage, bytes } = setup({
|
||||||
|
zoomFor: (height) => {
|
||||||
|
const zoom = coverageZoomForHeight(height);
|
||||||
|
return zoom == null ? null : { zoom, kind: 'sequence' };
|
||||||
|
},
|
||||||
|
});
|
||||||
|
coverage.refresh();
|
||||||
|
assert.equal(source.calls.length, 1, 'the tile is asked for');
|
||||||
|
assert.equal(source.calls[0].z, 14);
|
||||||
|
source.calls[0].resolve(bytes);
|
||||||
|
await settle();
|
||||||
|
assert.equal(viewer.scene.groundPrimitives.items.size, 1, 'its line drawn');
|
||||||
|
assert.equal(coverage.stats().hint, '');
|
||||||
|
coverage.clear();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('a zoom level is read from either shape; an overview or a bad answer draws nothing', () => {
|
||||||
|
assert.equal(coverageZoom(14), 14);
|
||||||
|
assert.equal(coverageZoom({ zoom: 15, kind: 'sequence' }), 15);
|
||||||
|
assert.equal(coverageZoom({ zoom: 12 }), 12);
|
||||||
|
assert.equal(coverageZoom({ zoom: 5, kind: 'overview' }), null, 'orbit');
|
||||||
|
assert.equal(coverageZoom(null), null);
|
||||||
|
assert.equal(coverageZoom(undefined), null);
|
||||||
|
assert.equal(coverageZoom({}), null);
|
||||||
|
assert.equal(coverageZoom(14.5), null);
|
||||||
|
assert.equal(coverageZoom('14'), null);
|
||||||
|
});
|
||||||
|
|
||||||
test('from orbit nothing is requested or drawn, and the hint says to zoom in', async () => {
|
test('from orbit nothing is requested or drawn, and the hint says to zoom in', async () => {
|
||||||
const { viewer, source, state, coverage, bytes } = setup();
|
const { viewer, source, state, coverage, bytes } = setup();
|
||||||
coverage.refresh();
|
coverage.refresh();
|
||||||
|
|||||||
Reference in new issue
Block a user