From 729bdb44138c3770afc8da0da89644cee6e5d13f Mon Sep 17 00:00:00 2001 From: Eugene Maksymenko Date: Wed, 28 Sep 2022 12:21:38 +0300 Subject: [PATCH] Keep map scale by adopting field of view on view port resize --- src/BasicWorldWindowController.js | 2 +- src/WorldWindow.js | 18 ++++++-- src/geom/Camera.js | 76 +++++++++++++++++++++++++++++-- 3 files changed, 87 insertions(+), 9 deletions(-) diff --git a/src/BasicWorldWindowController.js b/src/BasicWorldWindowController.js index 48b519a1e..0590006bd 100644 --- a/src/BasicWorldWindowController.js +++ b/src/BasicWorldWindowController.js @@ -457,7 +457,7 @@ define([ // Clamp tilt to between 0 and +90 to prevent the viewer from going upside down. lookAt.tilt = WWMath.clamp(lookAt.tilt, 0, 90); - // Normalize heading to between -180 and +180. + // Normalize roll to between -180 and +180. lookAt.roll = Angle.normalizedDegrees(lookAt.roll); // Apply 2D limits when the globe is 2D. diff --git a/src/WorldWindow.js b/src/WorldWindow.js index 6a4b37ffa..a76f9cccd 100644 --- a/src/WorldWindow.js +++ b/src/WorldWindow.js @@ -175,7 +175,7 @@ define([ * @type {Rectangle} * @readonly */ - this.viewport = new Rectangle(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); + this.viewport = new Rectangle(0, 0, 0, 0); /** * The globe displayed. @@ -811,13 +811,25 @@ define([ width = gl.canvas.clientWidth * this.pixelScale, height = gl.canvas.clientHeight * this.pixelScale; - if (gl.canvas.width != width || - gl.canvas.height != height) { + if (gl.canvas.width != width || gl.canvas.height != height + || this.viewport.width === 0 || this.viewport.height === 0) { // Make the canvas drawing buffer size match its screen size. gl.canvas.width = width; gl.canvas.height = height; + // Keep map scale by adopting field of view on view port resize + if (this.viewport.height !== 0) { + try { + this.camera.fieldOfView *= height / this.viewport.height; + } catch (ignore) { + // Keep original field of view in case new one does not fit requirements + } + } else { + // Initialize vertical field of view assuming that horizontal is 45 degrees + this.camera.fieldOfView = 45 * height / width; + } + // Set the WebGL viewport to match the canvas drawing buffer size. gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); this.viewport = new Rectangle(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); diff --git a/src/geom/Camera.js b/src/geom/Camera.js index a4dc60fc3..119c937b4 100644 --- a/src/geom/Camera.js +++ b/src/geom/Camera.js @@ -33,33 +33,99 @@ define([ */ this.position = new Position(30, -110, 10e6); + // Intentionally not documented + this._heading = 0; + + // Intentionally not documented + this._tilt = 0; + + // Intentionally not documented + this._roll = 0; + + // Intentionally not documented + this._fieldOfView = 45; + }; + + Object.defineProperties(Camera.prototype, { /** * Camera heading, in degrees clockwise from north. * @type {Number} * @default 0 + * @throws {ArgumentError} If the specified heading is out of range. */ - this.heading = 0; + heading: { + get: function () { + return this._heading; + }, + set: function (value) { + if (value < -180 || value > 180) { + throw new ArgumentError( + Logger.logMessage(Logger.LEVEL_SEVERE, "Camera", "setHeading", "Invalid heading") + ); + } + this._heading = value; + } + }, /** * Camera tilt, in degrees. * @default 0 + * @throws {ArgumentError} If the specified tilt is out of range. */ - this.tilt = 0; + tilt: { + get: function () { + return this._tilt; + }, + set: function (value) { + if (value < 0 || value > 90) { + throw new ArgumentError( + Logger.logMessage(Logger.LEVEL_SEVERE, "Camera", "setTilt", "Invalid tilt") + ); + } + this._tilt = value; + } + }, /** * Camera roll, in degrees. * @type {Number} * @default 0 + * @throws {ArgumentError} If the specified roll is out of range. */ - this.roll = 0; + roll: { + get: function () { + return this._roll; + }, + set: function (value) { + if (value < -180 || value > 180) { + throw new ArgumentError( + Logger.logMessage(Logger.LEVEL_SEVERE, "Camera", "setRoll", "Invalid roll") + ); + } + this._roll = value; + } + }, /** * Camera vertical field of view, in degrees * @type {Number} * @default 45 + * @throws {ArgumentError} If the specified field of view is out of range. */ - this.fieldOfView = 45; - }; + fieldOfView: { + get: function () { + return this._fieldOfView; + }, + set: function (value) { + if (value < 0 || value > 180) { + throw new ArgumentError( + Logger.logMessage(Logger.LEVEL_SEVERE, "Camera", "setFieldOfView", "Invalid field of view") + ); + } + this._fieldOfView = value; + } + } + }); /** * Indicates whether the components of this object are equal to those of a specified object.