diff --git a/CHANGES.md b/CHANGES.md index 3cae15c30998..4ac26e3471db 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -17,6 +17,8 @@ Change Log * Fix a race condition that would cause the terrain to continue loading and unloading or cause a crash when changing terrain providers. [#3690](https://github.com/AnalyticalGraphicsInc/cesium/issues/3690) * All external urls are now https by default to make Cesium work better with non-server-based applications. [#3650](https://github.com/AnalyticalGraphicsInc/cesium/issues/3650) * Fix issue where the `GroundPrimitive` volume was being clipped by the far plane. [#3706](https://github.com/AnalyticalGraphicsInc/cesium/issues/3706) +* Fixed issue where `Camera.computeViewRectangle` was incorrect when crossing the international date line [#3717](https://github.com/AnalyticalGraphicsInc/cesium/issues/3717) +* Added `Rectangle` result parameter to `Camera.computeViewRectangle` ### 1.19 - 2016-03-01 diff --git a/Source/Scene/Camera.js b/Source/Scene/Camera.js index 1b07fc3dbb6f..461467a412ca 100644 --- a/Source/Scene/Camera.js +++ b/Source/Scene/Camera.js @@ -2800,17 +2800,29 @@ define([ } var scratchPickCartesian2 = new Cartesian2(); - + var scratchRectCartesian = new Cartesian3(); + var cartoArray = [new Cartographic(), new Cartographic(), new Cartographic(), new Cartographic()]; + function addToResult(x, y, index, camera, ellipsoid, computedHorizonQuad) { + scratchPickCartesian2.x = x; + scratchPickCartesian2.y = y; + var r = camera.pickEllipsoid(scratchPickCartesian2, ellipsoid, scratchRectCartesian); + if (defined(r)) { + cartoArray[index] = ellipsoid.cartesianToCartographic(r, cartoArray[index]); + return 1; + } + cartoArray[index] = ellipsoid.cartesianToCartographic(computedHorizonQuad[index], cartoArray[index]); + return 0; + } /** * Computes the approximate visible rectangle on the ellipsoid. * * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid that you want to know the visible region. + * @param {Rectangle} [result] The rectangle in which to store the result * * @returns {Rectangle|undefined} The visible rectangle or undefined if the ellipsoid isn't visible at all. */ - Camera.prototype.computeViewRectangle = function(ellipsoid) { + Camera.prototype.computeViewRectangle = function(ellipsoid, result) { ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84); - var cullingVolume = this.frustum.computeCullingVolume(this.positionWC, this.directionWC, this.upWC); var boundingSphere = new BoundingSphere(Cartesian3.ZERO, ellipsoid.maximumRadius); var visibility = cullingVolume.computeVisibility(boundingSphere); @@ -2822,45 +2834,27 @@ define([ var width = canvas.clientWidth; var height = canvas.clientHeight; - var that = this; - var computedHorizonQuad; - var cartographics = []; var successfulPickCount = 0; - function addToResult(x, y, index) { - scratchPickCartesian2.x = x; - scratchPickCartesian2.y = y; - var r = that.pickEllipsoid(scratchPickCartesian2, ellipsoid, new Cartesian3()); - if (defined(r)) { - cartographics.push(ellipsoid.cartesianToCartographic(r)); - ++successfulPickCount; - } else { - if (!defined(computedHorizonQuad)) { - computedHorizonQuad = computeHorizonQuad(that, ellipsoid); - } - cartographics.push(ellipsoid.cartesianToCartographic(computedHorizonQuad[index])); - } - } - addToResult(0, 0, 0); - addToResult(0, height, 1); - addToResult(width, height, 2); - addToResult(width, 0, 3); + var computedHorizonQuad = computeHorizonQuad(this, ellipsoid); + + successfulPickCount += addToResult(0, 0, 0, this, ellipsoid, computedHorizonQuad); + successfulPickCount += addToResult(0, height, 1, this, ellipsoid, computedHorizonQuad); + successfulPickCount += addToResult(width, height, 2, this, ellipsoid, computedHorizonQuad); + successfulPickCount += addToResult(width, 0, 3, this, ellipsoid, computedHorizonQuad); - if (successfulPickCount === 0 || successfulPickCount === 1) { + if (successfulPickCount < 2) { // If we have space non-globe in 3 or 4 corners then return the whole globe return Rectangle.MAX_VALUE; } - var i; - var point; - var cartographicsCount = cartographics.length; + result = Rectangle.fromCartographicArray(cartoArray, result); // Detect if we go over the poles var distance = 0; - var lastLon = cartographics[cartographicsCount-1].longitude; - for (i=0;i CesiumMath.PI) { // Crossed the dateline @@ -2872,22 +2866,11 @@ define([ lastLon = lon; } - var result; - for(i=0;i= 0.0) { + if (cartoArray[0].latitude >= 0.0) { result.north = CesiumMath.PI_OVER_TWO; } else { result.south = -CesiumMath.PI_OVER_TWO; diff --git a/Specs/Scene/CameraSpec.js b/Specs/Scene/CameraSpec.js index ee815fbabb69..2c9983aac417 100644 --- a/Specs/Scene/CameraSpec.js +++ b/Specs/Scene/CameraSpec.js @@ -2350,7 +2350,7 @@ defineSuite([ }).toThrowDeveloperError(); }); - it('computeViewRegion when zoomed in', function() { + it('computeViewRectangle when zoomed in', function() { scene.mode = SceneMode.SCENE3D; var position = Cartesian3.clone(Cartesian3.UNIT_X); @@ -2367,12 +2367,15 @@ defineSuite([ expect(rect).toEqual(correctResult); }); - it('computeViewRegion when zoomed in to pole', function() { + it('computeViewRectangle when zoomed in to pole', function() { scene.mode = SceneMode.SCENE3D; var position = Cartesian3.clone(Cartesian3.UNIT_Z); Cartesian3.multiplyByScalar(position, 7000000, position); camera.position = position; + camera.up = Cartesian3.clone(Cartesian3.UNIT_Y); + camera.direction = Cartesian3.negate(Cartesian3.UNIT_Z, new Cartesian3()); + camera.right = Cartesian3.cross(camera.direction, camera.up, new Cartesian3()); var correctResult = new Rectangle(-CesiumMath.PI, 1.4961779388065022, CesiumMath.PI, CesiumMath.PI_OVER_TWO); @@ -2380,7 +2383,23 @@ defineSuite([ expect(rect).toEqual(correctResult); }); - it('computeViewRegion when zoomed out', function() { + it('computeViewRectangle when zoomed in to IDL', function() { + scene.mode = SceneMode.SCENE3D; + + var position = Cartesian3.negate(Cartesian3.UNIT_X, new Cartesian3()); + Cartesian3.multiplyByScalar(position, 7000000, position); + camera.position = position; + camera.up = Cartesian3.clone(Cartesian3.UNIT_Z); + camera.direction = Cartesian3.clone(Cartesian3.UNIT_X, new Cartesian3()); + camera.right = Cartesian3.cross(camera.direction, camera.up, new Cartesian3()); + + var correctResult = new Rectangle(3.0837016481160435, -0.04365869998457809, -3.0837016481160435, 0.04365869998457809); + + var rect = camera.computeViewRectangle(); + expect(rect).toEqual(correctResult); + }); + + it('computeViewRectangle when zoomed out', function() { scene.mode = SceneMode.SCENE3D; var position = Cartesian3.clone(Cartesian3.UNIT_X); @@ -2395,7 +2414,7 @@ defineSuite([ expect(rect).toEqual(Rectangle.MAX_VALUE); }); - it('computeViewRegion when globe isn\'t visible', function() { + it('computeViewRectangle when globe isn\'t visible', function() { scene.mode = SceneMode.SCENE3D; var position = Cartesian3.clone(Cartesian3.UNIT_X);