From fe0e9ff376f2225aacd5f1a418aa3854ec2dfbce Mon Sep 17 00:00:00 2001 From: kiselev-dv Date: Mon, 27 Feb 2017 19:21:00 -0400 Subject: [PATCH 01/12] Implemented options for camera fly to: flyOverLon - longitude which we want camerra to cross duiring the flight flyOverLonweight - Fly over the lon specifyed via flyOverLon only if that way is not longer than short way times flyOverLonWeight. --- Apps/Flyto/CesiumViewer.css | 41 ++++++++++++++++ Apps/Flyto/CesiumViewer.js | 76 ++++++++++++++++++++++++++++++ Apps/Flyto/CesiumViewerStartup.js | 11 +++++ Apps/Flyto/Images/ajax-loader.gif | Bin 0 -> 6820 bytes Apps/Flyto/favicon.ico | Bin 0 -> 49334 bytes Apps/Flyto/index.html | 19 ++++++++ Source/Scene/Camera.js | 4 ++ Source/Scene/CameraFlightPath.js | 67 ++++++++++++++++++++++---- 8 files changed, 210 insertions(+), 8 deletions(-) create mode 100644 Apps/Flyto/CesiumViewer.css create mode 100644 Apps/Flyto/CesiumViewer.js create mode 100644 Apps/Flyto/CesiumViewerStartup.js create mode 100644 Apps/Flyto/Images/ajax-loader.gif create mode 100644 Apps/Flyto/favicon.ico create mode 100644 Apps/Flyto/index.html diff --git a/Apps/Flyto/CesiumViewer.css b/Apps/Flyto/CesiumViewer.css new file mode 100644 index 000000000000..9345e863194e --- /dev/null +++ b/Apps/Flyto/CesiumViewer.css @@ -0,0 +1,41 @@ +@import url(../../Source/Widgets/widgets.css); +@import url(../../Source/Widgets/lighter.css); + +html { + height: 100%; +} + +body { + height: 100%; + width: 100%; + margin: 0; + overflow: hidden; + padding: 0; + background: #000; +} + +.fullWindow { + position: absolute; + top: 0; + left: 0; + height: 100%; + width: 100%; + margin: 0; + overflow: hidden; + padding: 0; + font-family: sans-serif; +} + +.loadingIndicator { + display: block; + position: absolute; + top: 50%; + left: 50%; + margin-top: -33px; + margin-left: -33px; + width: 66px; + height: 66px; + background-position: center; + background-repeat: no-repeat; + background-image: url(Images/ajax-loader.gif); +} diff --git a/Apps/Flyto/CesiumViewer.js b/Apps/Flyto/CesiumViewer.js new file mode 100644 index 000000000000..ccc28ccc7b8f --- /dev/null +++ b/Apps/Flyto/CesiumViewer.js @@ -0,0 +1,76 @@ +/*global define*/ +define([ + 'Cesium/Core/Cartesian3', + 'Cesium/Core/Math', + 'Cesium/Core/objectToQuery', + 'Cesium/Core/queryToObject', + 'Cesium/Scene/createOpenStreetMapImageryProvider', + 'Cesium/Widgets/Viewer/Viewer', + 'domReady!' + ], function( + Cartesian3, + CesiumMath, + objectToQuery, + queryToObject, + createOpenStreetMapImageryProvider, + Viewer) { + 'use strict'; + + var endUserOptions = queryToObject(window.location.search.substring(1)); + + var viewer = new Viewer('cesiumContainer', { + baseLayerPicker: false, + imageryProvider: createOpenStreetMapImageryProvider() + }); + + // 35.6891 139.7899 tokyo + // 37.7757 -122.4382 SF + + viewer.camera.flyTo({ + duration: 0, + destination : Cartesian3.fromDegrees(139.7899, 35.6891, 35000.0), + orientation : { + heading : CesiumMath.toRadians(15), + pitch : CesiumMath.toRadians(-35.0), + roll : 0.0 + } + }); + + var flyToSF = function(){ + viewer.camera.flyTo({ + duration: 10, + destination : Cartesian3.fromDegrees(-122.4382, 37.7757, 45000.0), + orientation : { + heading : CesiumMath.toRadians(25), + pitch : CesiumMath.toRadians(-15.0), + roll : 0.0 + }, + maximumHeight: 1000000, + flyOverLon: CesiumMath.toRadians(0), + flyOverLonWeight: 3 + }); + }; + + var flyToTokyo = function(){ + viewer.camera.flyTo({ + duration: 10, + destination : Cartesian3.fromDegrees(139.7899, 35.6891, 35000.0), + orientation : { + heading : CesiumMath.toRadians(15), + pitch : CesiumMath.toRadians(-35.0), + roll : 0.0 + }, + maximumHeight: 1000000, + flyOverLon: CesiumMath.toRadians(0), + flyOverLonWeight: 3 + }); + }; + + setTimeout(function() { + flyToSF(); + setTimeout(flyToTokyo, 10 * 1000) + }, 30 * 1000); + + var loadingIndicator = document.getElementById('loadingIndicator'); + loadingIndicator.style.display = 'none'; +}); diff --git a/Apps/Flyto/CesiumViewerStartup.js b/Apps/Flyto/CesiumViewerStartup.js new file mode 100644 index 000000000000..0860c9af7dfa --- /dev/null +++ b/Apps/Flyto/CesiumViewerStartup.js @@ -0,0 +1,11 @@ +/*global require*/ +require({ + baseUrl : '.', + paths : { + domReady : '../../ThirdParty/requirejs-2.1.20/domReady', + Cesium : '../../Source' + } +}, [ + 'CesiumViewer' + ], function() { +}); diff --git a/Apps/Flyto/Images/ajax-loader.gif b/Apps/Flyto/Images/ajax-loader.gif new file mode 100644 index 0000000000000000000000000000000000000000..9b92efe0fa2cb697be67dfcf6797d87ce8a5a29f GIT binary patch literal 6820 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 uc?}St78)98nW+WAb7Xe@{dpJY4>H%lq + + + + + + + + + Cesium Viewer + + + + + +
+
+ + diff --git a/Source/Scene/Camera.js b/Source/Scene/Camera.js index f3b2a91eabca..398ace166cbd 100644 --- a/Source/Scene/Camera.js +++ b/Source/Scene/Camera.js @@ -2570,6 +2570,8 @@ define([ * @param {Camera~FlightCancelledCallback} [options.cancel] The function to execute if the flight is cancelled. * @param {Matrix4} [options.endTransform] Transform matrix representing the reference frame the camera will be in when the flight is completed. * @param {Number} [options.maximumHeight] The maximum height at the peak of the flight. + * @param {Number} [options.flyOverLon] There are always two ways between 2 points on globe. This option force camera to choose fight direction to fly over that longitude. + * @param {Number} [options.flyOverLonWeight] Fly over the lon specifyed via flyOverLon only if that way is not longer than short way times flyOverLonWeight. * @param {EasingFunction|EasingFunction~Callback} [options.easingFunction] Controls how the time is interpolated over the duration of the flight. * * @exception {DeveloperError} If either direction or up is given, then both are required. @@ -2665,6 +2667,8 @@ define([ newOptions.endTransform = options.endTransform; newOptions.convert = isRectangle ? false : options.convert; newOptions.maximumHeight = options.maximumHeight; + newOptions.flyOverLon = options.flyOverLon; + newOptions.flyOverLonWeight = options.flyOverLonWeight; newOptions.easingFunction = options.easingFunction; var scene = this._scene; diff --git a/Source/Scene/CameraFlightPath.js b/Source/Scene/CameraFlightPath.js index 3aacb634f9b1..d0562c2614fd 100644 --- a/Source/Scene/CameraFlightPath.js +++ b/Source/Scene/CameraFlightPath.js @@ -140,7 +140,9 @@ define([ var scratchStartCart = new Cartographic(); var scratchEndCart = new Cartographic(); - function createUpdate3D(scene, duration, destination, heading, pitch, roll, optionAltitude) { + function createUpdate3D(scene, duration, destination, heading, pitch, roll, + optionAltitude, optionFlyOverLon, optionFlyOverLonWeight) { + var camera = scene.camera; var projection = scene.mapProjection; var ellipsoid = projection.ellipsoid; @@ -154,11 +156,58 @@ define([ startCart.longitude = CesiumMath.zeroToTwoPi(startCart.longitude); destCart.longitude = CesiumMath.zeroToTwoPi(destCart.longitude); - var diff = startCart.longitude - destCart.longitude; - if (diff < -CesiumMath.PI) { - startCart.longitude += CesiumMath.TWO_PI; - } else if (diff > CesiumMath.PI) { - destCart.longitude += CesiumMath.TWO_PI; + if (defined(optionFlyOverLon)) { + var intrmdtLon = CesiumMath.zeroToTwoPi(optionFlyOverLon); + + var lonMin = Math.min(startCart.longitude, destCart.longitude); + var lonMax = Math.max(startCart.longitude, destCart.longitude); + + var intrmdtInside = (intrmdtLon >= lonMin && intrmdtLon <= lonMax); + + if (defined(optionFlyOverLonWeight)) { + // Distance inside (0...2Pi) + var din = Math.abs(startCart.longitude - destCart.longitude); + // Distance outside (0...2Pi) + var dot = CesiumMath.TWO_PI - din; + + var hitDistance = intrmdtInside ? din : dot; + var offDistance = intrmdtInside ? dot : din; + + if (hitDistance < offDistance * optionFlyOverLonWeight) { + if (!intrmdtInside) { + // Adjust start/stop to hit intrmdtLon + flip(); + } + } + else { + useShortest(); + } + } + else if (!intrmdtInside) { + // Adjust start/stop to hit intrmdtLon + flip(); + } + } + else { + useShortest(); + } + + function flip() { + if (startCart.longitude < destCart.longitude) { + startCart.longitude += CesiumMath.TWO_PI + } + else { + destCart.longitude += CesiumMath.TWO_PI + } + } + + function useShortest() { + var diff = startCart.longitude - destCart.longitude; + if (diff < -CesiumMath.PI) { + startCart.longitude += CesiumMath.TWO_PI; + } else if (diff > CesiumMath.PI) { + destCart.longitude += CesiumMath.TWO_PI; + } } var heightFunction = createHeightFunction(camera, destination, startCart.height, destCart.height, optionAltitude); @@ -264,6 +313,8 @@ define([ var projection = scene.mapProjection; var ellipsoid = projection.ellipsoid; var maximumHeight = options.maximumHeight; + var flyOverLon = options.flyOverLon; + var flyOverLonWeight = options.flyOverLonWeight; var easingFunction = options.easingFunction; if (convert && mode !== SceneMode.SCENE3D) { @@ -318,7 +369,7 @@ define([ if (duration <= 0.0) { var newOnComplete = function() { - var update = updateFunctions[mode](scene, 1.0, destination, heading, pitch, roll, maximumHeight); + var update = updateFunctions[mode](scene, 1.0, destination, heading, pitch, roll, maximumHeight, flyOverLon, flyOverLonWeight); update({ time: 1.0 }); if (typeof complete === 'function') { @@ -328,7 +379,7 @@ define([ return emptyFlight(newOnComplete, cancel); } - var update = updateFunctions[mode](scene, duration, destination, heading, pitch, roll, maximumHeight); + var update = updateFunctions[mode](scene, duration, destination, heading, pitch, roll, maximumHeight, flyOverLon, flyOverLonWeight); if (!defined(easingFunction)) { var startHeight = camera.positionCartographic.height; From a85ba83e9122803724c98923f8147d1786084f6f Mon Sep 17 00:00:00 2001 From: kiselev-dv Date: Tue, 28 Feb 2017 13:02:05 -0400 Subject: [PATCH 02/12] Add pitchAdjusAltitude This flyto option allows to point camera down duiring the flight if camera flyes higher than pitchAdjusAltitude That helps to keep Earth in sight duiring the long flights. --- Apps/Flyto/CesiumViewer.js | 47 +++++++++++++++++++++++++++----- Source/Scene/Camera.js | 2 ++ Source/Scene/CameraFlightPath.js | 32 +++++++++++++++++++--- 3 files changed, 70 insertions(+), 11 deletions(-) diff --git a/Apps/Flyto/CesiumViewer.js b/Apps/Flyto/CesiumViewer.js index ccc28ccc7b8f..066ab08c6f4f 100644 --- a/Apps/Flyto/CesiumViewer.js +++ b/Apps/Flyto/CesiumViewer.js @@ -23,9 +23,6 @@ define([ imageryProvider: createOpenStreetMapImageryProvider() }); - // 35.6891 139.7899 tokyo - // 37.7757 -122.4382 SF - viewer.camera.flyTo({ duration: 0, destination : Cartesian3.fromDegrees(139.7899, 35.6891, 35000.0), @@ -46,6 +43,7 @@ define([ roll : 0.0 }, maximumHeight: 1000000, + pitchAdjusAltitude: 10000, flyOverLon: CesiumMath.toRadians(0), flyOverLonWeight: 3 }); @@ -61,15 +59,50 @@ define([ roll : 0.0 }, maximumHeight: 1000000, + pitchAdjusAltitude: 10000, flyOverLon: CesiumMath.toRadians(0), flyOverLonWeight: 3 }); }; - setTimeout(function() { - flyToSF(); - setTimeout(flyToTokyo, 10 * 1000) - }, 30 * 1000); + function Tween() { + this.queue = []; + this.index = 0; + this.next = this.next.bind(this); + } + + Tween.prototype.add = function(f) { + this.queue.push(f); + return this; + }; + + Tween.prototype.run = function() { + this.queue[0](this.next); + }; + + Tween.prototype.next = function() { + var n = this.queue[this.index++]; + if (n) { + n(this.next); + } + }; + + function wrapWait(seconds, callback) { + var t = seconds * 1000; + return function(next) { + setTimeout(function() { + callback(); + if (next) { + next(); + } + }, t); + } + } + + new Tween() + .add(wrapWait(30, flyToSF)) + .add(wrapWait(10, flyToTokyo)) + .run(); var loadingIndicator = document.getElementById('loadingIndicator'); loadingIndicator.style.display = 'none'; diff --git a/Source/Scene/Camera.js b/Source/Scene/Camera.js index 398ace166cbd..2144b2257a76 100644 --- a/Source/Scene/Camera.js +++ b/Source/Scene/Camera.js @@ -2570,6 +2570,7 @@ define([ * @param {Camera~FlightCancelledCallback} [options.cancel] The function to execute if the flight is cancelled. * @param {Matrix4} [options.endTransform] Transform matrix representing the reference frame the camera will be in when the flight is completed. * @param {Number} [options.maximumHeight] The maximum height at the peak of the flight. + * @param {Number} [options.pitchAdjusAltitude] If camera flyes higher than that value, adjust pitch duiring the flight to look down, and keep Earth in viewport. * @param {Number} [options.flyOverLon] There are always two ways between 2 points on globe. This option force camera to choose fight direction to fly over that longitude. * @param {Number} [options.flyOverLonWeight] Fly over the lon specifyed via flyOverLon only if that way is not longer than short way times flyOverLonWeight. * @param {EasingFunction|EasingFunction~Callback} [options.easingFunction] Controls how the time is interpolated over the duration of the flight. @@ -2667,6 +2668,7 @@ define([ newOptions.endTransform = options.endTransform; newOptions.convert = isRectangle ? false : options.convert; newOptions.maximumHeight = options.maximumHeight; + newOptions.pitchAdjusAltitude = options.pitchAdjusAltitude; newOptions.flyOverLon = options.flyOverLon; newOptions.flyOverLonWeight = options.flyOverLonWeight; newOptions.easingFunction = options.easingFunction; diff --git a/Source/Scene/CameraFlightPath.js b/Source/Scene/CameraFlightPath.js index d0562c2614fd..7ddf3fb62b24 100644 --- a/Source/Scene/CameraFlightPath.js +++ b/Source/Scene/CameraFlightPath.js @@ -58,6 +58,21 @@ define([ var scratchCart = new Cartesian3(); var scratchCart2 = new Cartesian3(); + function createPitchFunction(camera, destination, startPitch, pitch, optionPitchAdjusAltitude, heightFunction) { + return function(time) { + var localTime = time * 3; + if (localTime <= 1) { + return CesiumMath.lerp(startPitch, -CesiumMath.PI_OVER_TWO, localTime); + } + else if(localTime >= 2) { + return CesiumMath.lerp(-CesiumMath.PI_OVER_TWO, pitch, localTime - 2); + } + else { + return -CesiumMath.PI_OVER_TWO; + } + }; + } + function createHeightFunction(camera, destination, startHeight, endHeight, optionAltitude) { var altitude = optionAltitude; var maxHeight = Math.max(startHeight, endHeight); @@ -141,7 +156,7 @@ define([ var scratchEndCart = new Cartographic(); function createUpdate3D(scene, duration, destination, heading, pitch, roll, - optionAltitude, optionFlyOverLon, optionFlyOverLonWeight) { + optionAltitude, optionFlyOverLon, optionFlyOverLonWeight, optionPitchAdjusAltitude) { var camera = scene.camera; var projection = scene.mapProjection; @@ -212,6 +227,14 @@ define([ var heightFunction = createHeightFunction(camera, destination, startCart.height, destCart.height, optionAltitude); + var pitchFunction = function(time) { + return CesiumMath.lerp(startPitch, pitch, time); + }; + + if (defined(optionPitchAdjusAltitude) && heightFunction(0.5) > optionPitchAdjusAltitude) { + pitchFunction = createPitchFunction(camera, destination, startPitch, pitch, optionPitchAdjusAltitude, heightFunction); + } + function update(value) { var time = value.time / duration; @@ -225,7 +248,7 @@ define([ destination : position, orientation: { heading : CesiumMath.lerp(startHeading, heading, time), - pitch : CesiumMath.lerp(startPitch, pitch, time), + pitch : pitchFunction(time), roll : CesiumMath.lerp(startRoll, roll, time) } }); @@ -315,6 +338,7 @@ define([ var maximumHeight = options.maximumHeight; var flyOverLon = options.flyOverLon; var flyOverLonWeight = options.flyOverLonWeight; + var pitchAdjusAltitude = options.pitchAdjusAltitude; var easingFunction = options.easingFunction; if (convert && mode !== SceneMode.SCENE3D) { @@ -369,7 +393,7 @@ define([ if (duration <= 0.0) { var newOnComplete = function() { - var update = updateFunctions[mode](scene, 1.0, destination, heading, pitch, roll, maximumHeight, flyOverLon, flyOverLonWeight); + var update = updateFunctions[mode](scene, 1.0, destination, heading, pitch, roll, maximumHeight, flyOverLon, flyOverLonWeight, pitchAdjusAltitude); update({ time: 1.0 }); if (typeof complete === 'function') { @@ -379,7 +403,7 @@ define([ return emptyFlight(newOnComplete, cancel); } - var update = updateFunctions[mode](scene, duration, destination, heading, pitch, roll, maximumHeight, flyOverLon, flyOverLonWeight); + var update = updateFunctions[mode](scene, duration, destination, heading, pitch, roll, maximumHeight, flyOverLon, flyOverLonWeight, pitchAdjusAltitude); if (!defined(easingFunction)) { var startHeight = camera.positionCartographic.height; From e949838f43c9b4fdcb74f06872e4e71c89ccccf6 Mon Sep 17 00:00:00 2001 From: kiselev-dv Date: Fri, 3 Mar 2017 17:03:03 -0400 Subject: [PATCH 03/12] Fly to options --- Apps/Flyto/CesiumViewer.js | 6 ++---- Source/Scene/Camera.js | 12 ++++++++--- Source/Scene/CameraFlightPath.js | 36 +++++++++++++++++++------------- 3 files changed, 33 insertions(+), 21 deletions(-) diff --git a/Apps/Flyto/CesiumViewer.js b/Apps/Flyto/CesiumViewer.js index 066ab08c6f4f..e2f2b508f07b 100644 --- a/Apps/Flyto/CesiumViewer.js +++ b/Apps/Flyto/CesiumViewer.js @@ -42,8 +42,7 @@ define([ pitch : CesiumMath.toRadians(-15.0), roll : 0.0 }, - maximumHeight: 1000000, - pitchAdjusAltitude: 10000, + pitchAdjustAltitude: 10000, flyOverLon: CesiumMath.toRadians(0), flyOverLonWeight: 3 }); @@ -58,8 +57,7 @@ define([ pitch : CesiumMath.toRadians(-35.0), roll : 0.0 }, - maximumHeight: 1000000, - pitchAdjusAltitude: 10000, + pitchAdjustAltitude: 10000, flyOverLon: CesiumMath.toRadians(0), flyOverLonWeight: 3 }); diff --git a/Source/Scene/Camera.js b/Source/Scene/Camera.js index 2144b2257a76..5aae6d190a97 100644 --- a/Source/Scene/Camera.js +++ b/Source/Scene/Camera.js @@ -2570,7 +2570,7 @@ define([ * @param {Camera~FlightCancelledCallback} [options.cancel] The function to execute if the flight is cancelled. * @param {Matrix4} [options.endTransform] Transform matrix representing the reference frame the camera will be in when the flight is completed. * @param {Number} [options.maximumHeight] The maximum height at the peak of the flight. - * @param {Number} [options.pitchAdjusAltitude] If camera flyes higher than that value, adjust pitch duiring the flight to look down, and keep Earth in viewport. + * @param {Number} [options.pitchAdjustAltitude] If camera flyes higher than that value, adjust pitch duiring the flight to look down, and keep Earth in viewport. * @param {Number} [options.flyOverLon] There are always two ways between 2 points on globe. This option force camera to choose fight direction to fly over that longitude. * @param {Number} [options.flyOverLonWeight] Fly over the lon specifyed via flyOverLon only if that way is not longer than short way times flyOverLonWeight. * @param {EasingFunction|EasingFunction~Callback} [options.easingFunction] Controls how the time is interpolated over the duration of the flight. @@ -2668,7 +2668,7 @@ define([ newOptions.endTransform = options.endTransform; newOptions.convert = isRectangle ? false : options.convert; newOptions.maximumHeight = options.maximumHeight; - newOptions.pitchAdjusAltitude = options.pitchAdjusAltitude; + newOptions.pitchAdjustAltitude = options.pitchAdjustAltitude; newOptions.flyOverLon = options.flyOverLon; newOptions.flyOverLonWeight = options.flyOverLonWeight; newOptions.easingFunction = options.easingFunction; @@ -2784,6 +2784,9 @@ define([ * @param {Camera~FlightCancelledCallback} [options.cancel] The function to execute if the flight is cancelled. * @param {Matrix4} [options.endTransform] Transform matrix representing the reference frame the camera will be in when the flight is completed. * @param {Number} [options.maximumHeight] The maximum height at the peak of the flight. + * @param {Number} [options.pitchAdjustAltitude] If camera flyes higher than that value, adjust pitch duiring the flight to look down, and keep Earth in viewport. + * @param {Number} [options.flyOverLon] There are always two ways between 2 points on globe. This option force camera to choose fight direction to fly over that longitude. + * @param {Number} [options.flyOverLonWeight] Fly over the lon specifyed via flyOverLon only if that way is not longer than short way times flyOverLonWeight. * @param {EasingFunction|EasingFunction~Callback} [options.easingFunction] Controls how the time is interpolated over the duration of the flight. */ Camera.prototype.flyToBoundingSphere = function(boundingSphere, options) { @@ -2841,7 +2844,10 @@ define([ cancel : options.cancel, endTransform : options.endTransform, maximumHeight : options.maximumHeight, - easingFunction : options.easingFunction + easingFunction : options.easingFunction, + flyOverLon : options.flyOverLon, + flyOverLonWeight : options.flyOverLonWeight, + pitchAdjustAltitude : options.pitchAdjustAltitude }); }; diff --git a/Source/Scene/CameraFlightPath.js b/Source/Scene/CameraFlightPath.js index 7ddf3fb62b24..f0ff2f9f12c1 100644 --- a/Source/Scene/CameraFlightPath.js +++ b/Source/Scene/CameraFlightPath.js @@ -58,17 +58,23 @@ define([ var scratchCart = new Cartesian3(); var scratchCart2 = new Cartesian3(); - function createPitchFunction(camera, destination, startPitch, pitch, optionPitchAdjusAltitude, heightFunction) { + function createPitchFunction(camera, destination, startPitch, endPitch, optionPitchAdjustAltitude, heightFunction) { + var startHeight = heightFunction(0.0); + var endHeight = heightFunction(1.0); + var middleHeight = heightFunction(0.5); + + var d1 = (middleHeight - startHeight) * 1.0; + var d2 = (middleHeight - endHeight) * 1.0; + return function(time) { - var localTime = time * 3; - if (localTime <= 1) { - return CesiumMath.lerp(startPitch, -CesiumMath.PI_OVER_TWO, localTime); - } - else if(localTime >= 2) { - return CesiumMath.lerp(-CesiumMath.PI_OVER_TWO, pitch, localTime - 2); + var altitude = heightFunction(time); + if (time <= 0.5) { + var t1 = (altitude - startHeight) * 1.0 / d1; + return CesiumMath.lerp(startPitch, -CesiumMath.PI_OVER_TWO, t1); } else { - return -CesiumMath.PI_OVER_TWO; + var t2 = (altitude - endHeight) * 1.0 / d2; + return CesiumMath.lerp(-CesiumMath.PI_OVER_TWO, endPitch, 1 - t2); } }; } @@ -156,7 +162,7 @@ define([ var scratchEndCart = new Cartographic(); function createUpdate3D(scene, duration, destination, heading, pitch, roll, - optionAltitude, optionFlyOverLon, optionFlyOverLonWeight, optionPitchAdjusAltitude) { + optionAltitude, optionFlyOverLon, optionFlyOverLonWeight, optionPitchAdjustAltitude) { var camera = scene.camera; var projection = scene.mapProjection; @@ -231,8 +237,8 @@ define([ return CesiumMath.lerp(startPitch, pitch, time); }; - if (defined(optionPitchAdjusAltitude) && heightFunction(0.5) > optionPitchAdjusAltitude) { - pitchFunction = createPitchFunction(camera, destination, startPitch, pitch, optionPitchAdjusAltitude, heightFunction); + if (defined(optionPitchAdjustAltitude) && heightFunction(0.5) > optionPitchAdjustAltitude) { + pitchFunction = createPitchFunction(camera, destination, startPitch, pitch, optionPitchAdjustAltitude, heightFunction); } function update(value) { @@ -338,7 +344,7 @@ define([ var maximumHeight = options.maximumHeight; var flyOverLon = options.flyOverLon; var flyOverLonWeight = options.flyOverLonWeight; - var pitchAdjusAltitude = options.pitchAdjusAltitude; + var pitchAdjustAltitude = options.pitchAdjustAltitude; var easingFunction = options.easingFunction; if (convert && mode !== SceneMode.SCENE3D) { @@ -393,7 +399,8 @@ define([ if (duration <= 0.0) { var newOnComplete = function() { - var update = updateFunctions[mode](scene, 1.0, destination, heading, pitch, roll, maximumHeight, flyOverLon, flyOverLonWeight, pitchAdjusAltitude); + var update = updateFunctions[mode](scene, 1.0, destination, heading, pitch, roll, + maximumHeight, flyOverLon, flyOverLonWeight, pitchAdjustAltitude); update({ time: 1.0 }); if (typeof complete === 'function') { @@ -403,7 +410,8 @@ define([ return emptyFlight(newOnComplete, cancel); } - var update = updateFunctions[mode](scene, duration, destination, heading, pitch, roll, maximumHeight, flyOverLon, flyOverLonWeight, pitchAdjusAltitude); + var update = updateFunctions[mode](scene, duration, destination, heading, pitch, roll, + maximumHeight, flyOverLon, flyOverLonWeight, pitchAdjustAltitude); if (!defined(easingFunction)) { var startHeight = camera.positionCartographic.height; From 8a88486e36f03980ed222bf0fa6a0c43aa97c700 Mon Sep 17 00:00:00 2001 From: kiselev-dv Date: Mon, 6 Mar 2017 11:45:51 -0400 Subject: [PATCH 04/12] Fixed jsHint warnings and errors --- Apps/Flyto/CesiumViewer.js | 14 ++++++-------- Source/Scene/CameraFlightPath.js | 10 +++++----- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/Apps/Flyto/CesiumViewer.js b/Apps/Flyto/CesiumViewer.js index e2f2b508f07b..2cce91cc3a18 100644 --- a/Apps/Flyto/CesiumViewer.js +++ b/Apps/Flyto/CesiumViewer.js @@ -16,8 +16,6 @@ define([ Viewer) { 'use strict'; - var endUserOptions = queryToObject(window.location.search.substring(1)); - var viewer = new Viewer('cesiumContainer', { baseLayerPicker: false, imageryProvider: createOpenStreetMapImageryProvider() @@ -45,7 +43,7 @@ define([ pitchAdjustAltitude: 10000, flyOverLon: CesiumMath.toRadians(0), flyOverLonWeight: 3 - }); + }); }; var flyToTokyo = function(){ @@ -60,7 +58,7 @@ define([ pitchAdjustAltitude: 10000, flyOverLon: CesiumMath.toRadians(0), flyOverLonWeight: 3 - }); + }); }; function Tween() { @@ -69,16 +67,16 @@ define([ this.next = this.next.bind(this); } - Tween.prototype.add = function(f) { + Tween.prototype.add = function(f) { this.queue.push(f); return this; }; - Tween.prototype.run = function() { + Tween.prototype.run = function() { this.queue[0](this.next); }; - Tween.prototype.next = function() { + Tween.prototype.next = function() { var n = this.queue[this.index++]; if (n) { n(this.next); @@ -94,7 +92,7 @@ define([ next(); } }, t); - } + }; } new Tween() diff --git a/Source/Scene/CameraFlightPath.js b/Source/Scene/CameraFlightPath.js index f0ff2f9f12c1..24b5fba9905d 100644 --- a/Source/Scene/CameraFlightPath.js +++ b/Source/Scene/CameraFlightPath.js @@ -161,7 +161,7 @@ define([ var scratchStartCart = new Cartographic(); var scratchEndCart = new Cartographic(); - function createUpdate3D(scene, duration, destination, heading, pitch, roll, + function createUpdate3D(scene, duration, destination, heading, pitch, roll, optionAltitude, optionFlyOverLon, optionFlyOverLonWeight, optionPitchAdjustAltitude) { var camera = scene.camera; @@ -215,10 +215,10 @@ define([ function flip() { if (startCart.longitude < destCart.longitude) { - startCart.longitude += CesiumMath.TWO_PI + startCart.longitude += CesiumMath.TWO_PI; } else { - destCart.longitude += CesiumMath.TWO_PI + destCart.longitude += CesiumMath.TWO_PI; } } @@ -399,7 +399,7 @@ define([ if (duration <= 0.0) { var newOnComplete = function() { - var update = updateFunctions[mode](scene, 1.0, destination, heading, pitch, roll, + var update = updateFunctions[mode](scene, 1.0, destination, heading, pitch, roll, maximumHeight, flyOverLon, flyOverLonWeight, pitchAdjustAltitude); update({ time: 1.0 }); @@ -410,7 +410,7 @@ define([ return emptyFlight(newOnComplete, cancel); } - var update = updateFunctions[mode](scene, duration, destination, heading, pitch, roll, + var update = updateFunctions[mode](scene, duration, destination, heading, pitch, roll, maximumHeight, flyOverLon, flyOverLonWeight, pitchAdjustAltitude); if (!defined(easingFunction)) { From e332c3c4423944a5b33269b21961fd37ca83a478 Mon Sep 17 00:00:00 2001 From: kiselev-dv Date: Wed, 8 Mar 2017 19:08:05 -0400 Subject: [PATCH 05/12] Removed Apps/Flyto --- Apps/Flyto/CesiumViewer.css | 41 ------------ Apps/Flyto/CesiumViewer.js | 105 ------------------------------ Apps/Flyto/CesiumViewerStartup.js | 11 ---- Apps/Flyto/Images/ajax-loader.gif | Bin 6820 -> 0 bytes Apps/Flyto/favicon.ico | Bin 49334 -> 0 bytes Apps/Flyto/index.html | 19 ------ 6 files changed, 176 deletions(-) delete mode 100644 Apps/Flyto/CesiumViewer.css delete mode 100644 Apps/Flyto/CesiumViewer.js delete mode 100644 Apps/Flyto/CesiumViewerStartup.js delete mode 100644 Apps/Flyto/Images/ajax-loader.gif delete mode 100644 Apps/Flyto/favicon.ico delete mode 100644 Apps/Flyto/index.html diff --git a/Apps/Flyto/CesiumViewer.css b/Apps/Flyto/CesiumViewer.css deleted file mode 100644 index 9345e863194e..000000000000 --- a/Apps/Flyto/CesiumViewer.css +++ /dev/null @@ -1,41 +0,0 @@ -@import url(../../Source/Widgets/widgets.css); -@import url(../../Source/Widgets/lighter.css); - -html { - height: 100%; -} - -body { - height: 100%; - width: 100%; - margin: 0; - overflow: hidden; - padding: 0; - background: #000; -} - -.fullWindow { - position: absolute; - top: 0; - left: 0; - height: 100%; - width: 100%; - margin: 0; - overflow: hidden; - padding: 0; - font-family: sans-serif; -} - -.loadingIndicator { - display: block; - position: absolute; - top: 50%; - left: 50%; - margin-top: -33px; - margin-left: -33px; - width: 66px; - height: 66px; - background-position: center; - background-repeat: no-repeat; - background-image: url(Images/ajax-loader.gif); -} diff --git a/Apps/Flyto/CesiumViewer.js b/Apps/Flyto/CesiumViewer.js deleted file mode 100644 index 2cce91cc3a18..000000000000 --- a/Apps/Flyto/CesiumViewer.js +++ /dev/null @@ -1,105 +0,0 @@ -/*global define*/ -define([ - 'Cesium/Core/Cartesian3', - 'Cesium/Core/Math', - 'Cesium/Core/objectToQuery', - 'Cesium/Core/queryToObject', - 'Cesium/Scene/createOpenStreetMapImageryProvider', - 'Cesium/Widgets/Viewer/Viewer', - 'domReady!' - ], function( - Cartesian3, - CesiumMath, - objectToQuery, - queryToObject, - createOpenStreetMapImageryProvider, - Viewer) { - 'use strict'; - - var viewer = new Viewer('cesiumContainer', { - baseLayerPicker: false, - imageryProvider: createOpenStreetMapImageryProvider() - }); - - viewer.camera.flyTo({ - duration: 0, - destination : Cartesian3.fromDegrees(139.7899, 35.6891, 35000.0), - orientation : { - heading : CesiumMath.toRadians(15), - pitch : CesiumMath.toRadians(-35.0), - roll : 0.0 - } - }); - - var flyToSF = function(){ - viewer.camera.flyTo({ - duration: 10, - destination : Cartesian3.fromDegrees(-122.4382, 37.7757, 45000.0), - orientation : { - heading : CesiumMath.toRadians(25), - pitch : CesiumMath.toRadians(-15.0), - roll : 0.0 - }, - pitchAdjustAltitude: 10000, - flyOverLon: CesiumMath.toRadians(0), - flyOverLonWeight: 3 - }); - }; - - var flyToTokyo = function(){ - viewer.camera.flyTo({ - duration: 10, - destination : Cartesian3.fromDegrees(139.7899, 35.6891, 35000.0), - orientation : { - heading : CesiumMath.toRadians(15), - pitch : CesiumMath.toRadians(-35.0), - roll : 0.0 - }, - pitchAdjustAltitude: 10000, - flyOverLon: CesiumMath.toRadians(0), - flyOverLonWeight: 3 - }); - }; - - function Tween() { - this.queue = []; - this.index = 0; - this.next = this.next.bind(this); - } - - Tween.prototype.add = function(f) { - this.queue.push(f); - return this; - }; - - Tween.prototype.run = function() { - this.queue[0](this.next); - }; - - Tween.prototype.next = function() { - var n = this.queue[this.index++]; - if (n) { - n(this.next); - } - }; - - function wrapWait(seconds, callback) { - var t = seconds * 1000; - return function(next) { - setTimeout(function() { - callback(); - if (next) { - next(); - } - }, t); - }; - } - - new Tween() - .add(wrapWait(30, flyToSF)) - .add(wrapWait(10, flyToTokyo)) - .run(); - - var loadingIndicator = document.getElementById('loadingIndicator'); - loadingIndicator.style.display = 'none'; -}); diff --git a/Apps/Flyto/CesiumViewerStartup.js b/Apps/Flyto/CesiumViewerStartup.js deleted file mode 100644 index 0860c9af7dfa..000000000000 --- a/Apps/Flyto/CesiumViewerStartup.js +++ /dev/null @@ -1,11 +0,0 @@ -/*global require*/ -require({ - baseUrl : '.', - paths : { - domReady : '../../ThirdParty/requirejs-2.1.20/domReady', - Cesium : '../../Source' - } -}, [ - 'CesiumViewer' - ], function() { -}); diff --git a/Apps/Flyto/Images/ajax-loader.gif b/Apps/Flyto/Images/ajax-loader.gif deleted file mode 100644 index 9b92efe0fa2cb697be67dfcf6797d87ce8a5a29f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6820 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 uc?}St78)98nW+WAb7Xe@{dpJY4>H%lq - - - - - - - - - Cesium Viewer - - - - - -
-
- - From a8f7c1951e42b5996bbd8845c5ce8e113e6be610 Mon Sep 17 00:00:00 2001 From: kiselev-dv Date: Wed, 8 Mar 2017 19:10:06 -0400 Subject: [PATCH 06/12] Renamed options to meet cesium convention --- Source/Scene/Camera.js | 26 +++++++++++++------------- Source/Scene/CameraFlightPath.js | 26 +++++++++++++------------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/Source/Scene/Camera.js b/Source/Scene/Camera.js index 5aae6d190a97..d482b7ce700c 100644 --- a/Source/Scene/Camera.js +++ b/Source/Scene/Camera.js @@ -261,7 +261,7 @@ define([ Camera.DEFAULT_VIEW_FACTOR = 0.5; /** - * The default heading/pitch/range that is used when the camera flies to a location that contains a bounding sphere. + * The default heading/pitch/range that is used when the camera flies to a location that contains a bounding sphere. * @type HeadingPitchRange */ Camera.DEFAULT_OFFSET = new HeadingPitchRange(0.0, -CesiumMath.PI_OVER_FOUR, 0.0); @@ -2570,9 +2570,9 @@ define([ * @param {Camera~FlightCancelledCallback} [options.cancel] The function to execute if the flight is cancelled. * @param {Matrix4} [options.endTransform] Transform matrix representing the reference frame the camera will be in when the flight is completed. * @param {Number} [options.maximumHeight] The maximum height at the peak of the flight. - * @param {Number} [options.pitchAdjustAltitude] If camera flyes higher than that value, adjust pitch duiring the flight to look down, and keep Earth in viewport. - * @param {Number} [options.flyOverLon] There are always two ways between 2 points on globe. This option force camera to choose fight direction to fly over that longitude. - * @param {Number} [options.flyOverLonWeight] Fly over the lon specifyed via flyOverLon only if that way is not longer than short way times flyOverLonWeight. + * @param {Number} [options.pitchAdjustHeight] If camera flyes higher than that value, adjust pitch duiring the flight to look down, and keep Earth in viewport. + * @param {Number} [options.flyOverLongitude] There are always two ways between 2 points on globe. This option force camera to choose fight direction to fly over that longitude. + * @param {Number} [options.flyOverLongitudeWeight] Fly over the lon specifyed via flyOverLongitude only if that way is not longer than short way times flyOverLongitudeWeight. * @param {EasingFunction|EasingFunction~Callback} [options.easingFunction] Controls how the time is interpolated over the duration of the flight. * * @exception {DeveloperError} If either direction or up is given, then both are required. @@ -2668,9 +2668,9 @@ define([ newOptions.endTransform = options.endTransform; newOptions.convert = isRectangle ? false : options.convert; newOptions.maximumHeight = options.maximumHeight; - newOptions.pitchAdjustAltitude = options.pitchAdjustAltitude; - newOptions.flyOverLon = options.flyOverLon; - newOptions.flyOverLonWeight = options.flyOverLonWeight; + newOptions.pitchAdjustHeight = options.pitchAdjustHeight; + newOptions.flyOverLongitude = options.flyOverLongitude; + newOptions.flyOverLongitudeWeight = options.flyOverLongitudeWeight; newOptions.easingFunction = options.easingFunction; var scene = this._scene; @@ -2784,9 +2784,9 @@ define([ * @param {Camera~FlightCancelledCallback} [options.cancel] The function to execute if the flight is cancelled. * @param {Matrix4} [options.endTransform] Transform matrix representing the reference frame the camera will be in when the flight is completed. * @param {Number} [options.maximumHeight] The maximum height at the peak of the flight. - * @param {Number} [options.pitchAdjustAltitude] If camera flyes higher than that value, adjust pitch duiring the flight to look down, and keep Earth in viewport. - * @param {Number} [options.flyOverLon] There are always two ways between 2 points on globe. This option force camera to choose fight direction to fly over that longitude. - * @param {Number} [options.flyOverLonWeight] Fly over the lon specifyed via flyOverLon only if that way is not longer than short way times flyOverLonWeight. + * @param {Number} [options.pitchAdjustHeight] If camera flyes higher than that value, adjust pitch duiring the flight to look down, and keep Earth in viewport. + * @param {Number} [options.flyOverLongitude] There are always two ways between 2 points on globe. This option force camera to choose fight direction to fly over that longitude. + * @param {Number} [options.flyOverLongitudeWeight] Fly over the lon specifyed via flyOverLongitude only if that way is not longer than short way times flyOverLongitudeWeight. * @param {EasingFunction|EasingFunction~Callback} [options.easingFunction] Controls how the time is interpolated over the duration of the flight. */ Camera.prototype.flyToBoundingSphere = function(boundingSphere, options) { @@ -2845,9 +2845,9 @@ define([ endTransform : options.endTransform, maximumHeight : options.maximumHeight, easingFunction : options.easingFunction, - flyOverLon : options.flyOverLon, - flyOverLonWeight : options.flyOverLonWeight, - pitchAdjustAltitude : options.pitchAdjustAltitude + flyOverLongitude : options.flyOverLongitude, + flyOverLongitudeWeight : options.flyOverLongitudeWeight, + pitchAdjustHeight : options.pitchAdjustHeight }); }; diff --git a/Source/Scene/CameraFlightPath.js b/Source/Scene/CameraFlightPath.js index 24b5fba9905d..e4a723a9dd2c 100644 --- a/Source/Scene/CameraFlightPath.js +++ b/Source/Scene/CameraFlightPath.js @@ -58,7 +58,7 @@ define([ var scratchCart = new Cartesian3(); var scratchCart2 = new Cartesian3(); - function createPitchFunction(camera, destination, startPitch, endPitch, optionPitchAdjustAltitude, heightFunction) { + function createPitchFunction(camera, destination, startPitch, endPitch, optionPitchAdjustHeight, heightFunction) { var startHeight = heightFunction(0.0); var endHeight = heightFunction(1.0); var middleHeight = heightFunction(0.5); @@ -162,7 +162,7 @@ define([ var scratchEndCart = new Cartographic(); function createUpdate3D(scene, duration, destination, heading, pitch, roll, - optionAltitude, optionFlyOverLon, optionFlyOverLonWeight, optionPitchAdjustAltitude) { + optionAltitude, optionFlyOverLongitude, optionFlyOverLongitudeWeight, optionPitchAdjustHeight) { var camera = scene.camera; var projection = scene.mapProjection; @@ -177,15 +177,15 @@ define([ startCart.longitude = CesiumMath.zeroToTwoPi(startCart.longitude); destCart.longitude = CesiumMath.zeroToTwoPi(destCart.longitude); - if (defined(optionFlyOverLon)) { - var intrmdtLon = CesiumMath.zeroToTwoPi(optionFlyOverLon); + if (defined(optionFlyOverLongitude)) { + var intrmdtLon = CesiumMath.zeroToTwoPi(optionFlyOverLongitude); var lonMin = Math.min(startCart.longitude, destCart.longitude); var lonMax = Math.max(startCart.longitude, destCart.longitude); var intrmdtInside = (intrmdtLon >= lonMin && intrmdtLon <= lonMax); - if (defined(optionFlyOverLonWeight)) { + if (defined(optionFlyOverLongitudeWeight)) { // Distance inside (0...2Pi) var din = Math.abs(startCart.longitude - destCart.longitude); // Distance outside (0...2Pi) @@ -194,7 +194,7 @@ define([ var hitDistance = intrmdtInside ? din : dot; var offDistance = intrmdtInside ? dot : din; - if (hitDistance < offDistance * optionFlyOverLonWeight) { + if (hitDistance < offDistance * optionFlyOverLongitudeWeight) { if (!intrmdtInside) { // Adjust start/stop to hit intrmdtLon flip(); @@ -237,8 +237,8 @@ define([ return CesiumMath.lerp(startPitch, pitch, time); }; - if (defined(optionPitchAdjustAltitude) && heightFunction(0.5) > optionPitchAdjustAltitude) { - pitchFunction = createPitchFunction(camera, destination, startPitch, pitch, optionPitchAdjustAltitude, heightFunction); + if (defined(optionPitchAdjustHeight) && heightFunction(0.5) > optionPitchAdjustHeight) { + pitchFunction = createPitchFunction(camera, destination, startPitch, pitch, optionPitchAdjustHeight, heightFunction); } function update(value) { @@ -342,9 +342,9 @@ define([ var projection = scene.mapProjection; var ellipsoid = projection.ellipsoid; var maximumHeight = options.maximumHeight; - var flyOverLon = options.flyOverLon; - var flyOverLonWeight = options.flyOverLonWeight; - var pitchAdjustAltitude = options.pitchAdjustAltitude; + var flyOverLongitude = options.flyOverLongitude; + var flyOverLongitudeWeight = options.flyOverLongitudeWeight; + var pitchAdjustHeight = options.pitchAdjustHeight; var easingFunction = options.easingFunction; if (convert && mode !== SceneMode.SCENE3D) { @@ -400,7 +400,7 @@ define([ if (duration <= 0.0) { var newOnComplete = function() { var update = updateFunctions[mode](scene, 1.0, destination, heading, pitch, roll, - maximumHeight, flyOverLon, flyOverLonWeight, pitchAdjustAltitude); + maximumHeight, flyOverLongitude, flyOverLongitudeWeight, pitchAdjustHeight); update({ time: 1.0 }); if (typeof complete === 'function') { @@ -411,7 +411,7 @@ define([ } var update = updateFunctions[mode](scene, duration, destination, heading, pitch, roll, - maximumHeight, flyOverLon, flyOverLonWeight, pitchAdjustAltitude); + maximumHeight, flyOverLongitude, flyOverLongitudeWeight, pitchAdjustHeight); if (!defined(easingFunction)) { var startHeight = camera.positionCartographic.height; From cde37f02be072154e6e04bc49c8a36f6e9baa80a Mon Sep 17 00:00:00 2001 From: kiselev-dv Date: Thu, 9 Mar 2017 16:50:27 -0400 Subject: [PATCH 07/12] Unit tests stub --- Specs/Scene/CameraFlightPathSpec.js | 40 +++++++++++++++++++++++++++++ Specs/Scene/CameraSpec.js | 6 +++++ 2 files changed, 46 insertions(+) diff --git a/Specs/Scene/CameraFlightPathSpec.js b/Specs/Scene/CameraFlightPathSpec.js index 2b5ecc5dff4e..d67b560e8571 100644 --- a/Specs/Scene/CameraFlightPathSpec.js +++ b/Specs/Scene/CameraFlightPathSpec.js @@ -2,6 +2,7 @@ defineSuite([ 'Scene/CameraFlightPath', 'Core/Cartesian3', + 'Core/Cartographic', 'Core/Math', 'Scene/OrthographicFrustum', 'Scene/SceneMode', @@ -9,6 +10,7 @@ defineSuite([ ], function( CameraFlightPath, Cartesian3, + Cartographic, CesiumMath, OrthographicFrustum, SceneMode, @@ -379,6 +381,44 @@ defineSuite([ expect(camera.position).toEqualEpsilon(endPosition, CesiumMath.EPSILON12); }); + it('creates animation to hit flyOverLongitude', function() { + var camera = scene.camera; + var projection = scene.mapProjection; + var position = new Cartographic(); + + camera.position = Cartesian3.fromDegrees(10.0, 45.0, 1000.0); + + var endPosition = Cartesian3.fromDegrees(20.0, 45.0, 1000.0); + + var overLonFlight = CameraFlightPath.createTween(scene, { + destination : endPosition, + duration : 1.0, + flyOverLongitude: CesiumMath.toRadians(0.0) + }); + + var directFlight = CameraFlightPath.createTween(scene, { + destination : endPosition, + duration : 1.0 + }); + + expect(typeof overLonFlight.update).toEqual('function'); + expect(typeof directFlight.update).toEqual('function'); + + overLonFlight.update({ time : 0.1 }); + projection.ellipsoid.cartesianToCartographic(camera.position, position); + var lon = CesiumMath.toDegrees(position.longitude); + + expect(lon).toBeLessThan(10.0); + + directFlight.update({ time : 0.1 }); + projection.ellipsoid.cartesianToCartographic(camera.position, position); + lon = CesiumMath.toDegrees(position.longitude); + + expect(lon).toBeMoreThan(10.0); + expect(lon).toBeLessThan(20.0); + + }); + it('does not go above the maximum height', function() { var camera = scene.camera; diff --git a/Specs/Scene/CameraSpec.js b/Specs/Scene/CameraSpec.js index 87626ef2df70..c6653dbbf330 100644 --- a/Specs/Scene/CameraSpec.js +++ b/Specs/Scene/CameraSpec.js @@ -2117,6 +2117,9 @@ defineSuite([ endTransform : new Matrix4(), convert : true, maximumHeight : 100, + pitchAdjustHeight:101, + flyOverLongitude: 1, + flyOverLongitudeWeight: 20, easingFunction : function() { } }; @@ -2137,6 +2140,9 @@ defineSuite([ expect(passedOptions.convert).toBe(options.convert); expect(passedOptions.maximumHeight).toBe(options.maximumHeight); expect(passedOptions.easingFunction).toBe(options.easingFunction); + expect(passedOptions.pitchAdjustHeight).toBe(options.pitchAdjustHeight); + expect(passedOptions.flyOverLongitude).toBe(options.flyOverLongitude); + expect(passedOptions.flyOverLongitudeWeight).toBe(options.flyOverLongitudeWeight); }); it('can cancel a flight', function() { From f4d29ff1f537c2a03ce6173ac5fb39f683dcf487 Mon Sep 17 00:00:00 2001 From: kiselev-dv Date: Thu, 9 Mar 2017 21:18:11 -0400 Subject: [PATCH 08/12] Unit tests for flyOverLongitude and flyOverLongitudeWeight --- Source/Scene/CameraFlightPath.js | 79 ++++++++++++++++------------- Specs/Scene/CameraFlightPathSpec.js | 44 ++++++++++++++-- 2 files changed, 86 insertions(+), 37 deletions(-) diff --git a/Source/Scene/CameraFlightPath.js b/Source/Scene/CameraFlightPath.js index e4a723a9dd2c..ef4990488036 100644 --- a/Source/Scene/CameraFlightPath.js +++ b/Source/Scene/CameraFlightPath.js @@ -178,12 +178,12 @@ define([ destCart.longitude = CesiumMath.zeroToTwoPi(destCart.longitude); if (defined(optionFlyOverLongitude)) { - var intrmdtLon = CesiumMath.zeroToTwoPi(optionFlyOverLongitude); + var hitLon = CesiumMath.zeroToTwoPi(optionFlyOverLongitude); var lonMin = Math.min(startCart.longitude, destCart.longitude); var lonMax = Math.max(startCart.longitude, destCart.longitude); - var intrmdtInside = (intrmdtLon >= lonMin && intrmdtLon <= lonMax); + var hitInside = (hitLon >= lonMin && hitLon <= lonMax); if (defined(optionFlyOverLongitudeWeight)) { // Distance inside (0...2Pi) @@ -191,38 +191,37 @@ define([ // Distance outside (0...2Pi) var dot = CesiumMath.TWO_PI - din; - var hitDistance = intrmdtInside ? din : dot; - var offDistance = intrmdtInside ? dot : din; + var hitDistance = hitInside ? din : dot; + var offDistance = hitInside ? dot : din; if (hitDistance < offDistance * optionFlyOverLongitudeWeight) { - if (!intrmdtInside) { - // Adjust start/stop to hit intrmdtLon - flip(); + if (!hitInside) { + // Adjust start/stop to hit hitLon + useLongestFlight(); } } else { - useShortest(); + useShortestFlight(); } } - else if (!intrmdtInside) { - // Adjust start/stop to hit intrmdtLon - flip(); + else if (!hitInside) { + // Adjust start/stop to hit hitLon + useLongestFlight(); } } else { - useShortest(); + useShortestFlight(); } - function flip() { + function useLongestFlight() { if (startCart.longitude < destCart.longitude) { startCart.longitude += CesiumMath.TWO_PI; - } - else { + } else { destCart.longitude += CesiumMath.TWO_PI; } } - function useShortest() { + function useShortestFlight() { var diff = startCart.longitude - destCart.longitude; if (diff < -CesiumMath.PI) { startCart.longitude += CesiumMath.TWO_PI; @@ -241,25 +240,37 @@ define([ pitchFunction = createPitchFunction(camera, destination, startPitch, pitch, optionPitchAdjustHeight, heightFunction); } - function update(value) { - var time = value.time / duration; - - var position = Cartesian3.fromRadians( - CesiumMath.lerp(startCart.longitude, destCart.longitude, time), - CesiumMath.lerp(startCart.latitude, destCart.latitude, time), - heightFunction(time) - ); - - camera.setView({ - destination : position, - orientation: { - heading : CesiumMath.lerp(startHeading, heading, time), - pitch : pitchFunction(time), - roll : CesiumMath.lerp(startRoll, roll, time) - } - }); + // Isolate scope for update function. + // to have local copies of vars used in lerp + // Othervise, if you call nex + // createUpdate3D (createAnimationTween) + // before you played animation, variables will be overwriten. + function isolateUpdateFunction() { + var startLongitude = startCart.longitude; + var destLongitude = destCart.longitude; + var startLatitude = startCart.latitude; + var destLatitude = destCart.latitude; + + return function update(value) { + var time = value.time / duration; + + var position = Cartesian3.fromRadians( + CesiumMath.lerp(startLongitude, destLongitude, time), + CesiumMath.lerp(startLatitude, destLatitude, time), + heightFunction(time) + ); + + camera.setView({ + destination : position, + orientation: { + heading : CesiumMath.lerp(startHeading, heading, time), + pitch : pitchFunction(time), + roll : CesiumMath.lerp(startRoll, roll, time) + } + }); + }; } - return update; + return isolateUpdateFunction(); } function createUpdate2D(scene, duration, destination, heading, pitch, roll, optionAltitude) { diff --git a/Specs/Scene/CameraFlightPathSpec.js b/Specs/Scene/CameraFlightPathSpec.js index d67b560e8571..f59aacbdf969 100644 --- a/Specs/Scene/CameraFlightPathSpec.js +++ b/Specs/Scene/CameraFlightPathSpec.js @@ -404,21 +404,59 @@ defineSuite([ expect(typeof overLonFlight.update).toEqual('function'); expect(typeof directFlight.update).toEqual('function'); - overLonFlight.update({ time : 0.1 }); + overLonFlight.update({ time : 0.3 }); projection.ellipsoid.cartesianToCartographic(camera.position, position); var lon = CesiumMath.toDegrees(position.longitude); expect(lon).toBeLessThan(10.0); - directFlight.update({ time : 0.1 }); + directFlight.update({ time : 0.3 }); projection.ellipsoid.cartesianToCartographic(camera.position, position); lon = CesiumMath.toDegrees(position.longitude); - expect(lon).toBeMoreThan(10.0); + expect(lon).toBeGreaterThan(10.0); expect(lon).toBeLessThan(20.0); }); + it('uses flyOverLongitudeWeight', function() { + var camera = scene.camera; + var projection = scene.mapProjection; + var position = new Cartographic(); + + camera.position = Cartesian3.fromDegrees(10.0, 45.0, 1000.0); + + var endPosition = Cartesian3.fromDegrees(50.0, 45.0, 1000.0); + + var overLonFlightSmallWeight = CameraFlightPath.createTween(scene, { + destination : endPosition, + duration : 1.0, + flyOverLongitude: CesiumMath.toRadians(0.0), + flyOverLongitudeWeight: 2 + }); + + var overLonFlightBigWeight = CameraFlightPath.createTween(scene, { + destination : endPosition, + duration : 1.0, + flyOverLongitude: CesiumMath.toRadians(0.0), + flyOverLongitudeWeight: 20 + }); + + overLonFlightBigWeight.update({ time : 0.3 }); + projection.ellipsoid.cartesianToCartographic(camera.position, position); + var lon = CesiumMath.toDegrees(position.longitude); + + expect(lon).toBeLessThan(10.0); + + overLonFlightSmallWeight.update({ time : 0.3 }); + projection.ellipsoid.cartesianToCartographic(camera.position, position); + lon = CesiumMath.toDegrees(position.longitude); + + expect(lon).toBeGreaterThan(10.0); + expect(lon).toBeLessThan(50.0); + + }); + it('does not go above the maximum height', function() { var camera = scene.camera; From b7466cc5f61b8621ffedc75e0a6563310729df10 Mon Sep 17 00:00:00 2001 From: kiselev-dv Date: Fri, 10 Mar 2017 10:50:03 -0400 Subject: [PATCH 09/12] * Test for pitch adjust height * Tests for fly over longitude --- Specs/Scene/CameraFlightPathSpec.js | 100 ++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/Specs/Scene/CameraFlightPathSpec.js b/Specs/Scene/CameraFlightPathSpec.js index f59aacbdf969..c96786598626 100644 --- a/Specs/Scene/CameraFlightPathSpec.js +++ b/Specs/Scene/CameraFlightPathSpec.js @@ -457,6 +457,106 @@ defineSuite([ }); + it('adjust pitch if camera flyes higher than pitchAdjustHeight', function(){ + var camera = scene.camera; + var duration = 5.0; + + camera.setView({ + destination : Cartesian3.fromDegrees(-20.0, 0.0, 1000.0), + orientation: { + heading : CesiumMath.toRadians(0.0), + pitch : CesiumMath.toRadians(-15.0), + roll : 0.0 + } + }); + + var startPitch = camera.pitch; + var endPitch = CesiumMath.toRadians(-45.0); + + var flight = CameraFlightPath.createTween(scene, { + destination : Cartesian3.fromDegrees(60.0, 0.0, 2000.0), + pitch : endPitch, + duration : duration, + pitchAdjustHeight: 2000 + }); + + flight.update({ time: 0.0 }); + expect(camera.pitch).toEqualEpsilon(startPitch, CesiumMath.EPSILON6); + + flight.update({ time : duration }); + expect(camera.pitch).toEqualEpsilon(endPitch, CesiumMath.EPSILON6); + + flight.update({ time : duration / 2.0 }); + expect(camera.pitch).toEqualEpsilon(-CesiumMath.PI_OVER_TWO, CesiumMath.EPSILON4); + + }); + + it('animation with flyOverLongitude is smooth over two pi', function() { + var camera = scene.camera; + var duration = 100.0; + var projection = scene.mapProjection; + var position = new Cartographic(); + + var startLonDegrees = 10.0; + var endLonDegrees = 20.0; + + camera.position = Cartesian3.fromDegrees(startLonDegrees, 45.0, 1000.0); + var endPosition = Cartesian3.fromDegrees(endLonDegrees, 45.0, 1000.0); + + var outsideTwoPiFlight = CameraFlightPath.createTween(scene, { + destination : endPosition, + duration : duration, + flyOverLongitude: CesiumMath.toRadians(0.0) + }); + + var prevLon = startLonDegrees; + var crossedDateChangesLine = 0; + for(var t = 1; t < duration; t++) { + outsideTwoPiFlight.update({ time: t }); + projection.ellipsoid.cartesianToCartographic(camera.position, position); + var lon = CesiumMath.toDegrees(position.longitude); + var d = lon - prevLon; + if (d > 0) { + expect(prevLon).toBeLessThan(-90); + crossedDateChangesLine ++; + d -= 360; + } + prevLon = lon; + expect(d).toBeLessThan(0); + } + + expect(crossedDateChangesLine).toEqual(1); + }); + + it('animation with flyOverLongitude is smooth', function() { + var camera = scene.camera; + var duration = 100.0; + var projection = scene.mapProjection; + var position = new Cartographic(); + + var startLonDegrees = -100.0; + var endLonDegrees = 100.0; + + camera.position = Cartesian3.fromDegrees(startLonDegrees, 45.0, 1000.0); + var endPosition = Cartesian3.fromDegrees(endLonDegrees, 45.0, 1000.0); + + var flight = CameraFlightPath.createTween(scene, { + destination : endPosition, + duration : duration, + flyOverLongitude: CesiumMath.toRadians(0.0) + }); + + var prevLon = startLonDegrees; + for(var t = 1; t < duration; t++) { + flight.update({ time: t }); + projection.ellipsoid.cartesianToCartographic(camera.position, position); + var lon = CesiumMath.toDegrees(position.longitude); + var d = lon - prevLon; + prevLon = lon; + expect(d).toBeGreaterThan(0); + } + }); + it('does not go above the maximum height', function() { var camera = scene.camera; From b3f4adf0155a76e243ad691089e9dca8fae3c9d2 Mon Sep 17 00:00:00 2001 From: kiselev-dv Date: Fri, 10 Mar 2017 11:20:19 -0400 Subject: [PATCH 10/12] Update CHANGES.md with flyTo options --- CHANGES.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 127a51a780b8..590799cc73f9 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,6 +3,10 @@ Change Log ### 1.32 - 2017-04-03 +* Added `Camera.flyTo` and `Camera.flyToBoundingSphere` options [#5070](https://github.com/AnalyticalGraphicsInc/cesium/pull/5070) + * `flyOverLongitude` to select one of two possible on Globe paths which camera should fly. + * `flyOverLongitudeWeight` to set a threshold: how many times the `flyOverLongitude` way can be than shortest path. + * `pitchAdjustHeight` to adjust camera pitch during exaggerated flights, to keep Earth in viewport. * Added the event `Viewer.trackedEntityChanged`, which is raised when the value of `viewer.trackedEntity` changes. [#5060](https://github.com/AnalyticalGraphicsInc/cesium/pull/5060) * Added `Camera.DEFAULT_OFFSET` for default view of objects with bounding spheres [#4936](https://github.com/AnalyticalGraphicsInc/cesium/pull/4936) * Fix crunch compressed textures in IE11. [#5057](https://github.com/AnalyticalGraphicsInc/cesium/pull/5057) From 42e9aebcc40b0def5f8631d147d95eccf4fee0b2 Mon Sep 17 00:00:00 2001 From: kiselev-dv Date: Fri, 10 Mar 2017 12:10:34 -0400 Subject: [PATCH 11/12] Sandcastle app for camera flyto options --- Apps/Sandcastle/gallery/Camera.html | 75 ++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 7 deletions(-) diff --git a/Apps/Sandcastle/gallery/Camera.html b/Apps/Sandcastle/gallery/Camera.html index 392abf6a8711..d50a3b5e4288 100644 --- a/Apps/Sandcastle/gallery/Camera.html +++ b/Apps/Sandcastle/gallery/Camera.html @@ -19,7 +19,7 @@