mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 10:24:02 +00:00
Merge remote-tracking branch 'origin/main' into perf/aircraft-label-candidates
This commit is contained in:
commit
e7cf071a1c
4 files changed
+67
-7
No files matched your search
@@ -105,6 +105,25 @@ function pointsOf(sequence) {
|
||||
* @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
|
||||
* 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
|
||||
* A decoded tile; sequences are `{id, parts, capturedAt, isPano}`. A
|
||||
* rejection may carry `keyRequired`, `keyRejected` or `retryAfterSec`.
|
||||
* @param {(heightM: number|null) => number|null} options.zoomFor
|
||||
* Tile zoom for a camera height above ground; null draws nothing.
|
||||
* @param {(heightM: number|null) => number|{zoom: number, kind?: string}|null} options.zoomFor
|
||||
* 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 {string} options.pickPrefix Pick-id prefix of the lines.
|
||||
* @param {string} options.renderKey Render-governor reason.
|
||||
@@ -380,7 +400,7 @@ export function createLineCoverage({
|
||||
const height = Number.isFinite(cameraHeight)
|
||||
? cameraHeight - (ground ?? 0)
|
||||
: null;
|
||||
const zoom = zoomFor(height);
|
||||
const zoom = coverageZoom(zoomFor(height));
|
||||
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
|
||||
// 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 * as Cesium from 'cesium';
|
||||
import {
|
||||
coverageZoom,
|
||||
createLineCoverage,
|
||||
freshCoverage,
|
||||
ZOOM_IN_HINT,
|
||||
@@ -28,7 +29,7 @@ const { maxSequences: COVERAGE_MAX_SEQUENCES, maxTiles: COVERAGE_MAX_TILES } =
|
||||
COVERAGE_TUNING;
|
||||
|
||||
/** Line coverage as the Mapillary provider builds it, over `source`. */
|
||||
function createCoverage({ state, source }) {
|
||||
function createCoverage({ state, source, zoomFor = coverageZoomForHeight }) {
|
||||
return createLineCoverage({
|
||||
state,
|
||||
fetchTile: async (tile, { signal }) =>
|
||||
@@ -36,7 +37,7 @@ function createCoverage({ state, source }) {
|
||||
await source.getTile('coverage', tile.z, tile.x, tile.y, { signal }),
|
||||
tile,
|
||||
),
|
||||
zoomFor: coverageZoomForHeight,
|
||||
zoomFor,
|
||||
colors: COLORS,
|
||||
pickPrefix: PICK_PREFIX.sequence,
|
||||
renderKey: 'mapillary-coverage',
|
||||
@@ -123,7 +124,7 @@ function deferredSource() {
|
||||
};
|
||||
}
|
||||
|
||||
function setup() {
|
||||
function setup({ zoomFor } = {}) {
|
||||
const centre = tileCentre(-121.4944, 38.5816);
|
||||
const viewer = fakeViewer({ lon: centre.lon, lat: centre.lat, height: 900 });
|
||||
const source = deferredSource();
|
||||
@@ -146,7 +147,7 @@ function setup() {
|
||||
},
|
||||
sequence: { selectedId: null },
|
||||
};
|
||||
const coverage = createCoverage({ state, source });
|
||||
const coverage = createCoverage({ state, source, zoomFor });
|
||||
const bytes = encodeCoverageTile(centre.tile, {
|
||||
sequences: [
|
||||
{
|
||||
@@ -239,6 +240,37 @@ test('panning off a tile that is still loading stops counting it as loading', as
|
||||
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 () => {
|
||||
const { viewer, source, state, coverage, bytes } = setup();
|
||||
coverage.refresh();
|
||||
|
||||
Reference in new issue
Block a user