maplibre-gl
Version:
BSD licensed community fork of mapbox-gl, a WebGL interactive maps library
115 lines (87 loc) • 4.96 kB
text/typescript
import {describe, beforeEach, test, expect, vi} from 'vitest';
import {createMap, beforeMapTest} from '../../util/test/util';
import {LngLat} from '../../geo/lng_lat';
import {type OverscaledTileID} from '../../source/tile_id';
import {type CameraOptions} from '../camera';
import {type Terrain} from '../../render/terrain';
import {mercatorZfromAltitude} from '../../geo/mercator_coordinate';
beforeEach(() => {
beforeMapTest();
global.fetch = null;
});
describe('calculateCameraOptionsFromTo', () => {
// Choose initial zoom to avoid center being constrained by mercator latitude limits.
test('pitch 90 with terrain', () => {
const map = createMap();
const mockedGetElevation = vi.fn((_lngLat: LngLat, _zoom: number) => 111200);
const terrainStub = {} as Terrain;
terrainStub.getElevationForLngLatZoom = mockedGetElevation;
map.terrain = terrainStub;
// distance between lng x and lng x+1 is 111.2km at same lat
// altitude same as center elevation => 90° pitch
const cameraOptions: CameraOptions = map.calculateCameraOptionsFromTo(new LngLat(1, 0), 111200, new LngLat(0, 0));
expect(cameraOptions).toBeDefined();
expect(cameraOptions.pitch).toBeCloseTo(90);
expect(mockedGetElevation.mock.calls).toHaveLength(1);
});
test('pitch 153.435 with terrain', () => {
const map = createMap();
const mockedGetElevation = vi.fn((_lngLat: LngLat, _zoom: number) => 111200 * 3);
const terrainStub = {} as Terrain;
terrainStub.getElevationForLngLatZoom = mockedGetElevation;
map.terrain = terrainStub;
// distance between lng x and lng x+1 is 111.2km at same lat
// (elevation difference of cam and center) / 2 = grounddistance =>
// acos(111.2 / sqrt(111.2² + (111.2 * 2)²)) = acos(1/sqrt(5)) => 63.435 + 90 = 153.435
const cameraOptions: CameraOptions = map.calculateCameraOptionsFromTo(new LngLat(1, 0), 111200, new LngLat(0, 0));
expect(cameraOptions).toBeDefined();
expect(cameraOptions.pitch).toBeCloseTo(153.435);
expect(mockedGetElevation.mock.calls).toHaveLength(1);
});
test('pitch 63 with terrain', () => {
const map = createMap();
const mockedGetElevation = vi.fn((_lngLat: LngLat, _zoom: number) => 111200 / 2);
const terrainStub = {} as Terrain;
terrainStub.getElevationForLngLatZoom = mockedGetElevation;
map.terrain = terrainStub;
// distance between lng x and lng x+1 is 111.2km at same lat
// (elevation difference of cam and center) * 2 = grounddistance =>
// acos(111.2 / sqrt(111.2² + (111.2 * 0.5)²)) = acos(1/sqrt(1.25)) => 90 (looking down) - 26.565 = 63.435
const cameraOptions: CameraOptions = map.calculateCameraOptionsFromTo(new LngLat(0, 0), 111200, new LngLat(1, 0));
expect(cameraOptions).toBeDefined();
expect(cameraOptions.pitch).toBeCloseTo(63.435);
expect(mockedGetElevation.mock.calls).toHaveLength(1);
});
test('zoom distance 1000', () => {
const map = createMap();
const mockedGetElevation = vi.fn((_lngLat: LngLat, _zoom: number) => 1000);
const terrainStub = {} as Terrain;
terrainStub.getElevationForLngLatZoom = mockedGetElevation;
map.terrain = terrainStub;
const expectedZoom = Math.log2(map.transform.cameraToCenterDistance / mercatorZfromAltitude(1000, 0) / map.transform.tileSize);
const cameraOptions = map.calculateCameraOptionsFromTo(new LngLat(0, 0), 0, new LngLat(0, 0));
expect(cameraOptions).toBeDefined();
expect(cameraOptions.zoom).toBeCloseTo(expectedZoom);
expect(mockedGetElevation.mock.calls).toHaveLength(1);
});
test('don\'t call getElevation when altitude supplied', () => {
const map = createMap();
const mockedGetElevation = vi.fn((_tileID: OverscaledTileID, _x: number, _y: number, _extent?: number) => 0);
const terrainStub = {} as Terrain;
terrainStub.getElevation = mockedGetElevation;
map.terrain = terrainStub;
const cameraOptions = map.calculateCameraOptionsFromTo(new LngLat(0, 0), 0, new LngLat(0, 0), 1000);
expect(cameraOptions).toBeDefined();
expect(mockedGetElevation.mock.calls).toHaveLength(0);
});
test('don\'t call getElevation when altitude 0 supplied', () => {
const map = createMap();
const mockedGetElevation = vi.fn((_tileID: OverscaledTileID, _x: number, _y: number, _extent?: number) => 0);
const terrainStub = {} as Terrain;
terrainStub.getElevation = mockedGetElevation;
map.terrain = terrainStub;
const cameraOptions = map.calculateCameraOptionsFromTo(new LngLat(0, 0), 0, new LngLat(1, 0), 0);
expect(cameraOptions).toBeDefined();
expect(mockedGetElevation.mock.calls).toHaveLength(0);
});
});