Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Projection and other classes to the new concept #5159

Closed
2 changes: 1 addition & 1 deletion src/geo/projection/camera_helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,4 +218,4 @@
};

return result;
}
}

Check warning on line 221 in src/geo/projection/camera_helper.ts

View check run for this annotation

Codecov / codecov/patch

src/geo/projection/camera_helper.ts#L221

Added line #L221 was not covered by tests
23 changes: 9 additions & 14 deletions src/geo/projection/covering_tiles.test.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,21 @@
import {beforeEach, describe, expect, test} from 'vitest';
import {GlobeTransform} from './globe_transform';
import {type GlobeProjection} from './globe_projection';
import {getGlobeProjectionMock} from '../../util/test/util';
import {globeConstants} from './vertical_perspective_projection';
import {LngLat} from '../lng_lat';
import {coveringTiles, coveringZoomLevel, type CoveringZoomOptions} from './covering_tiles';
import {OverscaledTileID} from '../../source/tile_id';
import {MercatorTransform} from './mercator_transform';
import {globeConstants} from './vertical_perspective_projection';

describe('coveringTiles', () => {
describe('globe', () => {
let globeProjectionMock: GlobeProjection;

beforeEach(() => {
globeProjectionMock = getGlobeProjectionMock();
// Force faster animations so we can use shorter sleeps when testing them
globeConstants.globeTransitionTimeSeconds = 0.1;
globeConstants.errorTransitionTimeSeconds = 0.1;
});

test('zoomed out', () => {
const transform = new GlobeTransform(globeProjectionMock);
const transform = new GlobeTransform();
transform.resize(128, 128);
transform.setCenter(new LngLat(0.0, 0.0));
transform.setZoom(-1);
Expand All @@ -35,7 +30,7 @@ describe('coveringTiles', () => {
});

test('zoomed in', () => {
const transform = new GlobeTransform(globeProjectionMock);
const transform = new GlobeTransform();
transform.resize(128, 128);
transform.setCenter(new LngLat(-0.02, 0.01));
transform.setZoom(3);
Expand All @@ -53,7 +48,7 @@ describe('coveringTiles', () => {
});

test('zoomed in 512x512', () => {
const transform = new GlobeTransform(globeProjectionMock);
const transform = new GlobeTransform();
transform.resize(512, 512);
transform.setCenter(new LngLat(-0.02, 0.01));
transform.setZoom(3);
Expand All @@ -79,7 +74,7 @@ describe('coveringTiles', () => {
});

test('pitched', () => {
const transform = new GlobeTransform(globeProjectionMock);
const transform = new GlobeTransform();
transform.resize(128, 128);
transform.setCenter(new LngLat(-0.002, 0.001));
transform.setZoom(8);
Expand All @@ -99,7 +94,7 @@ describe('coveringTiles', () => {
});

test('pitched+rotated', () => {
const transform = new GlobeTransform(globeProjectionMock);
const transform = new GlobeTransform();
transform.resize(128, 128);
transform.setCenter(new LngLat(-0.002, 0.001));
transform.setZoom(8);
Expand All @@ -124,7 +119,7 @@ describe('coveringTiles', () => {
});

test('antimeridian1', () => {
const transform = new GlobeTransform(globeProjectionMock);
const transform = new GlobeTransform();
transform.resize(128, 128);
transform.setCenter(new LngLat(179.99, -0.001));
transform.setZoom(5);
Expand All @@ -142,7 +137,7 @@ describe('coveringTiles', () => {
});

test('antimeridian2', () => {
const transform = new GlobeTransform(globeProjectionMock);
const transform = new GlobeTransform();
transform.resize(128, 128);
transform.setCenter(new LngLat(-179.99, 0.001));
transform.setZoom(5);
Expand All @@ -160,7 +155,7 @@ describe('coveringTiles', () => {
});

test('zoom < 0', () => {
const transform = new GlobeTransform(globeProjectionMock);
const transform = new GlobeTransform();
transform.resize(128, 128);
transform.setCenter(new LngLat(0.0, 80.0));
transform.setZoom(-0.5);
Expand Down
4 changes: 2 additions & 2 deletions src/geo/projection/globe_camera_helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export class GlobeCameraHelper implements ICameraHelper {
this._verticalPerspectiveCameraHelper = new VerticalPerspectiveCameraHelper();
}

get useGlobeControls(): boolean { return this._globe.useGlobeRendering; }
get useGlobeControls(): boolean { return this._globe.useGlobeControls; }

get currentHelper(): ICameraHelper {
return this.useGlobeControls ? this._verticalPerspectiveCameraHelper : this._mercatorCameraHelper;
Expand Down Expand Up @@ -63,4 +63,4 @@ export class GlobeCameraHelper implements ICameraHelper {
handleFlyTo(tr: ITransform, options: FlyToHandlerOptions): FlyToHandlerResult {
return this.currentHelper.handleFlyTo(tr, options);
}
}
}
23 changes: 4 additions & 19 deletions src/geo/projection/globe_projection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,6 @@ export class GlobeProjection extends Evented implements Projection {
_mercatorProjection: MercatorProjection;
_verticalPerspectiveProjection: VerticalPerspectiveProjection;

// HM TODO: remove this in the future
_useGlobeRendering: boolean = false;

constructor(projection?: ProjectionSpecification) {
super();
this._transitionable = new Transitionable(properties);
Expand All @@ -59,20 +56,8 @@ export class GlobeProjection extends Evented implements Projection {
return 1;
}

get useGlobeRendering(): boolean {
return this._useGlobeRendering;
}

set useGlobeRendering(value: boolean) {
this._useGlobeRendering = value;
}

get errorQueryLatitudeDegrees(): number { return this._verticalPerspectiveProjection.errorQueryLatitudeDegrees; }
set errorQueryLatitudeDegrees(value: number) { this._verticalPerspectiveProjection.errorQueryLatitudeDegrees = value; }
get latitudeErrorCorrectionRadians(): number { return this._verticalPerspectiveProjection.latitudeErrorCorrectionRadians; }

private get currentProjection(): Projection {
return this.useGlobeRendering ? this._verticalPerspectiveProjection : this._mercatorProjection;
return this.useGlobeControls ? this._verticalPerspectiveProjection : this._mercatorProjection;
}

setProjection(projection?: ProjectionSpecification) {
Expand All @@ -91,8 +76,8 @@ export class GlobeProjection extends Evented implements Projection {
this.properties = this._transitioning.possiblyEvaluate(parameters);
}

get name(): ProjectionSpecification['type'] {
return 'globe';
get name(): 'mercator' | 'vertical-perspective' {
return this.currentProjection.name;
}

get useSubdivision(): boolean {
Expand Down Expand Up @@ -129,7 +114,7 @@ export class GlobeProjection extends Evented implements Projection {
}

public isRenderingDirty(): boolean {
return this.currentProjection.isRenderingDirty(); // HM: TODO: should use hasTransition also
return this.hasTransition() || this.currentProjection.isRenderingDirty();
}

public updateGPUdependent(context: ProjectionGPUContext): void {
Expand Down
63 changes: 20 additions & 43 deletions src/geo/projection/globe_transform.test.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import {describe, expect, test} from 'vitest';
import {type GlobeProjection} from './globe_projection';
import {globeConstants} from './vertical_perspective_projection';
import {EXTENT} from '../../data/extent';
import Point from '@mapbox/point-geometry';
import {LngLat} from '../lng_lat';
import {GlobeTransform} from './globe_transform';
import {CanonicalTileID, OverscaledTileID, UnwrappedTileID} from '../../source/tile_id';
import {angularCoordinatesRadiansToVector, mercatorCoordinatesToAngularCoordinatesRadians, sphereSurfacePointToCoordinates} from './globe_utils';
import {expectToBeCloseToArray, getGlobeProjectionMock, sleep} from '../../util/test/util';
import {expectToBeCloseToArray} from '../../util/test/util';
import {MercatorCoordinate} from '../mercator_coordinate';
import {tileCoordinatesToLocation} from './mercator_utils';
import {MercatorTransform} from './mercator_transform';
import {globeConstants} from './vertical_perspective_projection';

function testPlaneAgainstLngLat(lngDegrees: number, latDegrees: number, plane: Array<number>) {
const lat = latDegrees / 180.0 * Math.PI;
Expand All @@ -28,21 +27,19 @@ function planeDistance(point: Array<number>, plane: Array<number>) {
return point[0] * plane[0] + point[1] * plane[1] + point[2] * plane[2] + plane[3];
}

function createGlobeTransform(globeProjection: GlobeProjection) {
const globeTransform = new GlobeTransform(globeProjection);
function createGlobeTransform() {
const globeTransform = new GlobeTransform();
globeTransform.resize(640, 480);
globeTransform.setFov(45);
return globeTransform;
}

describe('GlobeTransform', () => {
const globeProjectionMock = getGlobeProjectionMock();
// Force faster animations so we can use shorter sleeps when testing them
globeConstants.globeTransitionTimeSeconds = 0.1;
globeConstants.errorTransitionTimeSeconds = 0.1;

describe('getProjectionData', () => {
const globeTransform = createGlobeTransform(globeProjectionMock);
const globeTransform = createGlobeTransform();
test('mercator tile extents are set', () => {
const projectionData = globeTransform.getProjectionData({overscaledTileID: new OverscaledTileID(1, 0, 1, 1, 0)});
expectToBeCloseToArray(projectionData.tileMercatorCoords, [0.5, 0, 0.5 / EXTENT, 0.5 / EXTENT]);
Expand All @@ -60,7 +57,7 @@ describe('GlobeTransform', () => {
});

describe('clipping plane', () => {
const globeTransform = createGlobeTransform(globeProjectionMock);
const globeTransform = createGlobeTransform();

describe('general plane properties', () => {
const projectionData = globeTransform.getProjectionData({overscaledTileID: new OverscaledTileID(0, 0, 0, 0, 0)});
Expand Down Expand Up @@ -131,7 +128,7 @@ describe('GlobeTransform', () => {
test('camera position', () => {
const precisionDigits = 10;

const globeTransform = createGlobeTransform(globeProjectionMock);
const globeTransform = createGlobeTransform();
expectToBeCloseToArray(globeTransform.cameraPosition as Array<number>, [0, 0, 8.110445867263898], precisionDigits);

globeTransform.resize(512, 512);
Expand Down Expand Up @@ -175,7 +172,7 @@ describe('GlobeTransform', () => {

describe('project location to coordinates', () => {
const precisionDigits = 10;
const globeTransform = createGlobeTransform(globeProjectionMock);
const globeTransform = createGlobeTransform();

test('basic test', () => {
globeTransform.setCenter(new LngLat(0, 0));
Expand Down Expand Up @@ -209,7 +206,7 @@ describe('GlobeTransform', () => {
describe('unproject', () => {
test('unproject screen center', () => {
const precisionDigits = 10;
const globeTransform = createGlobeTransform(globeProjectionMock);
const globeTransform = createGlobeTransform();
let unprojected = globeTransform.screenPointToLocation(screenCenter);
expect(unprojected.lng).toBeCloseTo(globeTransform.center.lng, precisionDigits);
expect(unprojected.lat).toBeCloseTo(globeTransform.center.lat, precisionDigits);
Expand All @@ -227,7 +224,7 @@ describe('GlobeTransform', () => {

test('unproject point to the side', () => {
const precisionDigits = 10;
const globeTransform = createGlobeTransform(globeProjectionMock);
const globeTransform = createGlobeTransform();
let coords: LngLat;
let projected: Point;
let unprojected: LngLat;
Expand Down Expand Up @@ -257,7 +254,7 @@ describe('GlobeTransform', () => {
// This particular case turned out to be problematic, hence this test.

const precisionDigits = 10;
const globeTransform = createGlobeTransform(globeProjectionMock);
const globeTransform = createGlobeTransform();
// Transform settings from the render test projection/globe/fill-planet-pole
// See the expected result for how the globe should look with this transform.
globeTransform.resize(512, 512);
Expand Down Expand Up @@ -288,7 +285,7 @@ describe('GlobeTransform', () => {

test('unproject outside of sphere', () => {
const precisionDigits = 10;
const globeTransform = createGlobeTransform(globeProjectionMock);
const globeTransform = createGlobeTransform();
// Try unprojection a point somewhere above the western horizon
globeTransform.setPitch(60);
globeTransform.setBearing(-90);
Expand All @@ -300,7 +297,7 @@ describe('GlobeTransform', () => {

describe('setLocationAtPoint', () => {
const precisionDigits = 10;
const globeTransform = createGlobeTransform(globeProjectionMock);
const globeTransform = createGlobeTransform();
globeTransform.setZoom(1);
let coords: LngLat;
let point: Point;
Expand Down Expand Up @@ -399,7 +396,7 @@ describe('GlobeTransform', () => {
});

describe('isPointOnMapSurface', () => {
const globeTransform = new GlobeTransform(globeProjectionMock);
const globeTransform = new GlobeTransform();
globeTransform.resize(640, 480);
globeTransform.setZoom(1);

Expand Down Expand Up @@ -439,7 +436,7 @@ describe('GlobeTransform', () => {

test('pointCoordinate', () => {
const precisionDigits = 10;
const globeTransform = createGlobeTransform(globeProjectionMock);
const globeTransform = createGlobeTransform();
let coords: LngLat;
let coordsMercator: MercatorCoordinate;
let projected: Point;
Expand All @@ -463,7 +460,7 @@ describe('GlobeTransform', () => {
describe('getBounds', () => {
const precisionDigits = 10;

const globeTransform = new GlobeTransform(globeProjectionMock);
const globeTransform = new GlobeTransform();
globeTransform.resize(640, 480);

test('basic', () => {
Expand Down Expand Up @@ -509,7 +506,7 @@ describe('GlobeTransform', () => {

describe('projectTileCoordinates', () => {
const precisionDigits = 10;
const transform = new GlobeTransform(globeProjectionMock);
const transform = new GlobeTransform();
transform.resize(512, 512);
transform.setCenter(new LngLat(10.0, 50.0));
transform.setZoom(-1);
Expand Down Expand Up @@ -547,7 +544,7 @@ describe('GlobeTransform', () => {
});

describe('isLocationOccluded', () => {
const transform = new GlobeTransform(globeProjectionMock);
const transform = new GlobeTransform();
transform.resize(512, 512);
transform.setCenter(new LngLat(0.0, 0.0));
transform.setZoom(-1);
Expand Down Expand Up @@ -577,36 +574,16 @@ describe('GlobeTransform', () => {
});
});

test('transform and projection instance are synchronized properly', async () => {
const projectionMock = getGlobeProjectionMock();
const globeTransform = createGlobeTransform(projectionMock);
// projectionMock.useGlobeRendering and globeTransform.isGlobeRendering must have the same value
expect(projectionMock.useGlobeRendering).toBe(true);
expect(globeTransform.isGlobeRendering).toBe(projectionMock.useGlobeRendering);
globeTransform.setZoom(15);
globeTransform.newFrameUpdate();
await sleep(150);
globeTransform.newFrameUpdate();
expect(projectionMock.useGlobeRendering).toBe(false);
expect(globeTransform.isGlobeRendering).toBe(projectionMock.useGlobeRendering);
globeTransform.setZoom(1);
globeTransform.newFrameUpdate();
await sleep(150);
globeTransform.newFrameUpdate();
expect(globeTransform.isGlobeRendering).toBe(true);
expect(globeTransform.isGlobeRendering).toBe(projectionMock.useGlobeRendering);
});

describe('render world copies', () => {
test('change projection and make sure render world copies is kept', () => {
const globeTransform = createGlobeTransform(globeProjectionMock);
const globeTransform = createGlobeTransform();
globeTransform.setRenderWorldCopies(true);

expect(globeTransform.renderWorldCopies).toBeTruthy();
});

test('change transform and make sure render world copies is kept', () => {
const globeTransform = createGlobeTransform(globeProjectionMock);
const globeTransform = createGlobeTransform();
globeTransform.setRenderWorldCopies(true);
const mercator = new MercatorTransform(0, 1, 2, 3, false);
mercator.apply(globeTransform);
Expand Down
Loading
Loading