diff --git a/CHANGES.md b/CHANGES.md index c2d04162ecdd..599c90932dfb 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,6 +8,7 @@ Change Log * Fixed bug where if polylines were set to follow the surface of an undefined globe, Cesium would crash [#5413] https://github.com/AnalyticalGraphicsInc/cesium/pull/5413 * Fixed a bug where picking clusters would return undefined instead of a list of the clustered entities. [#5286](https://github.com/AnalyticalGraphicsInc/cesium/issues/5286) * Reduced the amount of Sun bloom post-process effect near the horizon. [#5381](https://github.com/AnalyticalGraphicsInc/cesium/issues/5381) +* Fixed a bug where camera zooming worked incorrectly when the display height was greater than the display width [#5421] (https://github.com/AnalyticalGraphicsInc/cesium/pull/5421) * Added Sandcastle demo for ArcticDEM data. [#5224](https://github.com/AnalyticalGraphicsInc/cesium/issues/5224) * `CzmlDataSource` and `KmlDataSource` load functions now take an optional `query` object, which will append query parameters to all network requests. [#5419](https://github.com/AnalyticalGraphicsInc/cesium/pull/5419), [#5434](https://github.com/AnalyticalGraphicsInc/cesium/pull/5434) * Fixed geocoder bug so geocoder can accurately handle NSEW inputs [#5407] (https://github.com/AnalyticalGraphicsInc/cesium/pull/5407) diff --git a/Source/Scene/Camera.js b/Source/Scene/Camera.js index d41ce2619e2e..029b8dfc6ad7 100644 --- a/Source/Scene/Camera.js +++ b/Source/Scene/Camera.js @@ -1820,30 +1820,57 @@ define([ } //>>includeEnd('debug'); + var ratio; amount = amount * 0.5; - var newRight = frustum.right - amount; - var newLeft = frustum.left + amount; - var maxRight = camera._maxCoord.x; - if (camera._scene.mapMode2D === MapMode2D.ROTATE) { - maxRight *= camera.maximumZoomFactor; - } + if((Math.abs(frustum.top) + Math.abs(frustum.bottom)) > (Math.abs(frustum.left) + Math.abs(frustum.right))) { + var newTop = frustum.top - amount; + var newBottom = frustum.bottom + amount; - if (newRight > maxRight) { - newRight = maxRight; - newLeft = -maxRight; - } + var maxBottom = camera._maxCoord.y; + if (camera._scene.mapMode2D === MapMode2D.ROTATE) { + maxBottom *= camera.maximumZoomFactor; + } - if (newRight <= newLeft) { - newRight = 1.0; - newLeft = -1.0; - } + if (newBottom > maxBottom) { + newBottom = maxBottom; + newTop = -maxBottom; + } + + if (newTop <= newBottom) { + newTop = 1.0; + newBottom = -1.0; + } + + ratio = frustum.right / frustum.top; + frustum.top = newTop; + frustum.bottom = newBottom; + frustum.right = frustum.top * ratio; + frustum.left = -frustum.right; + } else { + var newRight = frustum.right - amount; + var newLeft = frustum.left + amount; - var ratio = frustum.top / frustum.right; - frustum.right = newRight; - frustum.left = newLeft; - frustum.top = frustum.right * ratio; - frustum.bottom = -frustum.top; + var maxRight = camera._maxCoord.x; + if (camera._scene.mapMode2D === MapMode2D.ROTATE) { + maxRight *= camera.maximumZoomFactor; + } + + if (newRight > maxRight) { + newRight = maxRight; + newLeft = -maxRight; + } + + if (newRight <= newLeft) { + newRight = 1.0; + newLeft = -1.0; + } + ratio = frustum.top / frustum.right; + frustum.right = newRight; + frustum.left = newLeft; + frustum.top = frustum.right * ratio; + frustum.bottom = -frustum.top; + } } function zoom3D(camera, amount) { diff --git a/Specs/Scene/CameraSpec.js b/Specs/Scene/CameraSpec.js index ca983e47c813..63e083a0e037 100644 --- a/Specs/Scene/CameraSpec.js +++ b/Specs/Scene/CameraSpec.js @@ -1223,6 +1223,25 @@ defineSuite([ expect(camera.frustum.bottom).toEqual(-1.25, CesiumMath.EPSILON10); }); + it('zooms out 2D when frustrum has greater height than width', function() { + var frustum = new OrthographicOffCenterFrustum(); + frustum.near = 1.0; + frustum.far = 2.0; + frustum.left = -1.0; + frustum.right = 1.0; + frustum.top = 2.0; + frustum.bottom = -2.0; + camera.frustum = frustum; + + camera.update(SceneMode.SCENE2D); + + camera.zoomOut(zoomAmount); + expect(camera.frustum.right).toEqualEpsilon(1.25, CesiumMath.EPSILON10); + expect(camera.frustum.left).toEqual(-1.25, CesiumMath.EPSILON10); + expect(camera.frustum.top).toEqual(2.5, CesiumMath.EPSILON10); + expect(camera.frustum.bottom).toEqual(-2.5, CesiumMath.EPSILON10); + }); + it('zooms in 2D', function() { var frustum = new OrthographicOffCenterFrustum(); frustum.near = 1.0; @@ -1242,6 +1261,25 @@ defineSuite([ expect(camera.frustum.bottom).toEqual(-0.75, CesiumMath.EPSILON10); }); + it('zooms in 2D when frustrum has greater height than width', function() { + var frustum = new OrthographicOffCenterFrustum(); + frustum.near = 1.0; + frustum.far = 2.0; + frustum.left = -1.0; + frustum.right = 1.0; + frustum.top = 2.0; + frustum.bottom = -2.0; + camera.frustum = frustum; + + camera.update(SceneMode.SCENE2D); + + camera.zoomIn(zoomAmount); + expect(camera.frustum.right).toEqualEpsilon(0.75, CesiumMath.EPSILON10); + expect(camera.frustum.left).toEqual(-0.75, CesiumMath.EPSILON10); + expect(camera.frustum.top).toEqual(1.5, CesiumMath.EPSILON10); + expect(camera.frustum.bottom).toEqual(-1.5, CesiumMath.EPSILON10); + }); + it('clamps zoom out in 2D', function() { var frustum = new OrthographicOffCenterFrustum(); frustum.near = 1.0;