diff --git a/Apps/Sandcastle/gallery/3D Tiles Adjust Height.html b/Apps/Sandcastle/gallery/3D Tiles Adjust Height.html index 09813d39da55..638d3a2a1cb0 100644 --- a/Apps/Sandcastle/gallery/3D Tiles Adjust Height.html +++ b/Apps/Sandcastle/gallery/3D Tiles Adjust Height.html @@ -60,13 +60,11 @@ url : '../../../Specs/Data/Cesium3DTiles/Tilesets/Tileset' })); -tileset.readyPromise.then(function() { - var boundingSphere = tileset.boundingSphere; - viewer.camera.viewBoundingSphere(boundingSphere, new Cesium.HeadingPitchRange(0.0, -0.5, boundingSphere.radius * 2)); - viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY); -}).otherwise(function(error) { - throw(error); -}); + tileset.readyPromise.then(function() { + viewer.zoomTo(tileset, new Cesium.HeadingPitchRange(0.0, -0.5, tileset.boundingSphere.radius * 2.0)); + }).otherwise(function(error) { + throw(error); + }); Cesium.knockout.getObservable(viewModel, 'height').subscribe(function(height) { height = Number(height); diff --git a/Apps/Sandcastle/gallery/3D Tiles BIM.html b/Apps/Sandcastle/gallery/3D Tiles BIM.html index e87706a39f3e..7968388f78f1 100644 --- a/Apps/Sandcastle/gallery/3D Tiles BIM.html +++ b/Apps/Sandcastle/gallery/3D Tiles BIM.html @@ -34,9 +34,7 @@ })); tileset.readyPromise.then(function() { - var boundingSphere = tileset.boundingSphere; - viewer.camera.viewBoundingSphere(boundingSphere, new Cesium.HeadingPitchRange(0.5, -0.2, boundingSphere.radius * 4.0)); - viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY); + viewer.zoomTo(tileset, new Cesium.HeadingPitchRange(0.5, -0.2, tileset.boundingSphere.radius * 4.0)); }).otherwise(function(error) { throw(error); }); diff --git a/Apps/Sandcastle/gallery/3D Tiles Batch Table Hierarchy.html b/Apps/Sandcastle/gallery/3D Tiles Batch Table Hierarchy.html index 13252ef12ec6..b6da5ad00b42 100644 --- a/Apps/Sandcastle/gallery/3D Tiles Batch Table Hierarchy.html +++ b/Apps/Sandcastle/gallery/3D Tiles Batch Table Hierarchy.html @@ -88,10 +88,8 @@ url : '../../../Specs/Data/Cesium3DTiles/Hierarchy/BatchTableHierarchy' })); -tileset.readyPromise.then(function() { - var boundingSphere = tileset.boundingSphere; - viewer.camera.viewBoundingSphere(boundingSphere, new Cesium.HeadingPitchRange(0.0, -0.3, 0.0)); - viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY); +viewer.zoomTo(tileset, new Cesium.HeadingPitchRange(0.0, -0.3, 0.0)).otherwise(function(error) { + throw(error); }); var styles = []; diff --git a/Apps/Sandcastle/gallery/3D Tiles Clipping Planes.html b/Apps/Sandcastle/gallery/3D Tiles Clipping Planes.html index 8c962002ef2c..7622e5f4ff81 100644 --- a/Apps/Sandcastle/gallery/3D Tiles Clipping Planes.html +++ b/Apps/Sandcastle/gallery/3D Tiles Clipping Planes.html @@ -129,8 +129,7 @@ var boundingSphere = tileset.boundingSphere; var radius = boundingSphere.radius; - viewer.camera.viewBoundingSphere(boundingSphere, new Cesium.HeadingPitchRange(0.5, -0.2, radius * 4.0)); - viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY); + viewer.zoomTo(tileset, new Cesium.HeadingPitchRange(0.5, -0.2, radius * 4.0)); for (var i = 0; i < clippingPlanes.length; ++i) { var plane = clippingPlanes[i]; diff --git a/Apps/Sandcastle/gallery/3D Tiles Formats.html b/Apps/Sandcastle/gallery/3D Tiles Formats.html index 960ab825fc5e..f06f30585063 100644 --- a/Apps/Sandcastle/gallery/3D Tiles Formats.html +++ b/Apps/Sandcastle/gallery/3D Tiles Formats.html @@ -111,10 +111,8 @@ inspectorViewModel.tileset = tileset; scene.primitives.add(tileset); tileset.readyPromise.then(function(tileset) { - var boundingSphere = tileset.boundingSphere; - var range = Math.max(100.0 - boundingSphere.radius, 0.0); // Set a minimum offset of 100 meters - viewer.camera.viewBoundingSphere(boundingSphere, new Cesium.HeadingPitchRange(0, -2.0, range)); - viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY); + + viewer.zoomTo(tileset, new Cesium.HeadingPitchRange(0, -2.0, Math.max(100.0 - tileset.boundingSphere.radius, 0.0))); var properties = tileset.properties; if (Cesium.defined(properties) && Cesium.defined(properties.Height)) { diff --git a/Apps/Sandcastle/gallery/3D Tiles Inspector.html b/Apps/Sandcastle/gallery/3D Tiles Inspector.html index 2ed6d579def0..dace7c6c98db 100644 --- a/Apps/Sandcastle/gallery/3D Tiles Inspector.html +++ b/Apps/Sandcastle/gallery/3D Tiles Inspector.html @@ -36,9 +36,7 @@ })); tileset.readyPromise.then(function() { - var boundingSphere = tileset.boundingSphere; - viewer.camera.viewBoundingSphere(boundingSphere, new Cesium.HeadingPitchRange(0.0, -0.5, boundingSphere.radius / 4.0)); - viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY); + viewer.zoomTo(tileset, new Cesium.HeadingPitchRange(0.0, -0.5, tileset.boundingSphere.radius / 4.0)); }).otherwise(function(error) { throw(error); }); diff --git a/Apps/Sandcastle/gallery/3D Tiles Photogrammetry Classification.html b/Apps/Sandcastle/gallery/3D Tiles Photogrammetry Classification.html index 33f794c502ad..bc6322bc4b11 100644 --- a/Apps/Sandcastle/gallery/3D Tiles Photogrammetry Classification.html +++ b/Apps/Sandcastle/gallery/3D Tiles Photogrammetry Classification.html @@ -36,11 +36,7 @@ })); // Move the camera to view the tileset on load. -tileset.readyPromise.then(function() { - var boundingSphere = tileset.boundingSphere; - viewer.camera.viewBoundingSphere(boundingSphere, new Cesium.HeadingPitchRange(0.0, -0.5, boundingSphere.radius)); - viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY); -}).otherwise(function(error) { +viewer.zoomTo(tileset).otherwise(function(error) { throw(error); }); diff --git a/Apps/Sandcastle/gallery/3D Tiles Photogrammetry.html b/Apps/Sandcastle/gallery/3D Tiles Photogrammetry.html index 77e1c820c9c8..8aa0587a167a 100644 --- a/Apps/Sandcastle/gallery/3D Tiles Photogrammetry.html +++ b/Apps/Sandcastle/gallery/3D Tiles Photogrammetry.html @@ -32,11 +32,7 @@ url : 'https://beta.cesium.com/api/assets/1458?access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIxYmJiNTAxOC1lOTg5LTQzN2EtODg1OC0zMWJjM2IxNGNlYmMiLCJpZCI6NDQsImFzc2V0cyI6WzE0NThdLCJpYXQiOjE0OTkyNjM4MjB9.1WKijRa-ILkmG6utrhDWX6rDgasjD7dZv-G5ZyCmkKg' })); -tileset.readyPromise.then(function() { - var boundingSphere = tileset.boundingSphere; - viewer.camera.viewBoundingSphere(boundingSphere, new Cesium.HeadingPitchRange(0.0, -0.5, boundingSphere.radius)); - viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY); -}).otherwise(function(error) { +viewer.zoomTo(tileset).otherwise(function(error) { throw(error); }); //Sandcastle_End diff --git a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Styling.html b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Styling.html index 614c9563a6d2..ec9dce57a5cd 100644 --- a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Styling.html +++ b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Styling.html @@ -39,9 +39,7 @@ })); tileset.readyPromise.then(function() { - var boundingSphere = tileset.boundingSphere; - viewer.camera.viewBoundingSphere(boundingSphere, new Cesium.HeadingPitchRange(0.0, -1.0, 50.0)); - viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY); + viewer.zoomTo(tileset, new Cesium.HeadingPitchRange(0.0, -1.0, 50.0)); }).otherwise(function(error) { throw(error); }); diff --git a/Apps/Sandcastle/gallery/3D Tiles Point Cloud.html b/Apps/Sandcastle/gallery/3D Tiles Point Cloud.html index 1c8ebe13c6aa..ffce2edf8ab2 100644 --- a/Apps/Sandcastle/gallery/3D Tiles Point Cloud.html +++ b/Apps/Sandcastle/gallery/3D Tiles Point Cloud.html @@ -33,11 +33,7 @@ url : 'https://beta.cesium.com/api/assets/1460?access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIyMzk2YzJiOS1jZGFmLTRlZmYtYmQ4MS00NTA3NjEwMzViZTkiLCJpZCI6NDQsImFzc2V0cyI6WzE0NjBdLCJpYXQiOjE0OTkyNjQ3NTV9.oWjvN52CRQ-dk3xtvD4e8ZnOHZhoWSpJLlw115mbQJM' })); -tileset.readyPromise.then(function() { - var boundingSphere = tileset.boundingSphere; - viewer.camera.viewBoundingSphere(boundingSphere, new Cesium.HeadingPitchRange(0.0, -0.5, boundingSphere.radius)); - viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY); -}).otherwise(function(error) { +viewer.zoomTo(tileset).otherwise(function(error) { throw(error); }); //Sandcastle_End diff --git a/CHANGES.md b/CHANGES.md index aac3d79a4d13..c0b2b831fa45 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -25,9 +25,10 @@ Change Log * Only one node is supported. * Only one mesh per node is supported. * Only one primitive per mesh is supported. +* Updated documentation links to reflect new locations on cesiumjs.org and cesium.com. +* Updated 'Viewer.zoomTo' and 'Viewer.flyTo' to take in Cesium3DTilesets as a target and updated sandcastle 3DTileset examples to reflect this change * Fixed a glTF animation bug that caused certain animations to jitter. [#5740](https://github.com/AnalyticalGraphicsInc/cesium/pull/5740) * Fixed a bug when creating billboard and model entities without a globe. [#6109](https://github.com/AnalyticalGraphicsInc/cesium/pull/6109) -* Updated documentation links to reflect new locations on cesiumjs.org and cesium.com. * Added support for vertex shader uniforms when `tileset.colorBlendMode` is `MIX` or `REPLACE`. [#5874](https://github.com/AnalyticalGraphicsInc/cesium/pull/5874) ### 1.41 - 2018-01-02 diff --git a/Source/Widgets/Viewer/Viewer.js b/Source/Widgets/Viewer/Viewer.js index 69004305ff0b..fb4ad37900dc 100644 --- a/Source/Widgets/Viewer/Viewer.js +++ b/Source/Widgets/Viewer/Viewer.js @@ -1,6 +1,7 @@ define([ '../../Core/BoundingSphere', '../../Core/Cartesian3', + '../../Core/Check', '../../Core/Clock', '../../Core/defaultValue', '../../Core/defined', @@ -9,6 +10,7 @@ define([ '../../Core/DeveloperError', '../../Core/Event', '../../Core/EventHelper', + '../../Core/HeadingPitchRange', '../../Core/isArray', '../../Core/Matrix4', '../../Core/Rectangle', @@ -20,6 +22,7 @@ define([ '../../DataSources/Entity', '../../DataSources/EntityView', '../../DataSources/Property', + '../../Scene/Cesium3DTileset', '../../Scene/ImageryLayer', '../../Scene/SceneMode', '../../ThirdParty/knockout', @@ -46,6 +49,7 @@ define([ ], function( BoundingSphere, Cartesian3, + Check, Clock, defaultValue, defined, @@ -54,6 +58,7 @@ define([ DeveloperError, Event, EventHelper, + HeadingPitchRange, isArray, Matrix4, Rectangle, @@ -65,6 +70,7 @@ define([ Entity, EntityView, Property, + Cesium3DTileset, ImageryLayer, SceneMode, knockout, @@ -205,13 +211,13 @@ define([ if (defined(homeButton)) { homeButton.container.style.visibility = visibility; } - if(defined(sceneModePicker)) { + if (defined(sceneModePicker)) { sceneModePicker.container.style.visibility = visibility; } if (defined(projectionPicker)) { projectionPicker.container.style.visibility = visibility; } - if(defined(baseLayerPicker)) { + if (defined(baseLayerPicker)) { baseLayerPicker.container.style.visibility = visibility; } if (defined(animation)) { @@ -356,7 +362,7 @@ define([ options = defaultValue(options, defaultValue.EMPTY_OBJECT); var createBaseLayerPicker = (!defined(options.globe) || options.globe !== false) && - (!defined(options.baseLayerPicker) || options.baseLayerPicker !== false); + (!defined(options.baseLayerPicker) || options.baseLayerPicker !== false); //>>includeStart('debug', pragmas.debug); // If using BaseLayerPicker, imageryProvider is an invalid option @@ -431,7 +437,7 @@ Either specify options.terrainProvider instead or set options.baseLayerPicker to targetFrameRate : options.targetFrameRate, showRenderLoopErrors : options.showRenderLoopErrors, creditContainer : defined(options.creditContainer) ? options.creditContainer : bottomContainer, - creditViewport: options.creditViewport, + creditViewport : options.creditViewport, scene3DOnly : scene3DOnly, terrainExaggeration : options.terrainExaggeration, shadows : options.shadows, @@ -491,7 +497,7 @@ Either specify options.terrainProvider instead or set options.baseLayerPicker to toolbar.appendChild(geocoderContainer); geocoder = new Geocoder({ container : geocoderContainer, - geocoderServices: defined(options.geocoder) ? (isArray(options.geocoder) ? options.geocoder : [options.geocoder]) : undefined, + geocoderServices : defined(options.geocoder) ? (isArray(options.geocoder) ? options.geocoder : [options.geocoder]) : undefined, scene : cesiumWidget.scene }); // Subscribe to search so that we can clear the trackedEntity when it is clicked. @@ -1725,12 +1731,15 @@ Either specify options.terrainProvider instead or set options.baseLayerPicker to * target will be the range. The heading will be determined from the offset. If the heading cannot be * determined from the offset, the heading will be north.

* - * @param {Entity|Entity[]|EntityCollection|DataSource|ImageryLayer|Promise.} target The entity, array of entities, entity collection, data source or imagery layer to view. You can also pass a promise that resolves to one of the previously mentioned types. + * @param {Entity|Entity[]|EntityCollection|DataSource|ImageryLayer|Cesium3DTileset|Promise.} target The entity, array of entities, entity collection, data source, Cesium#DTileset, or imagery layer to view. You can also pass a promise that resolves to one of the previously mentioned types. * @param {HeadingPitchRange} [offset] The offset from the center of the entity in the local east-north-up reference frame. - * @returns {Promise.} A Promise that resolves to true if the zoom was successful or false if the entity is not currently visualized in the scene or the zoom was cancelled. + * @returns {Promise.} A Promise that resolves to true if the zoom was successful or false if the target is not currently visualized in the scene or the zoom was cancelled. */ Viewer.prototype.zoomTo = function(target, offset) { - return zoomToOrFly(this, target, offset, false); + var options = { + offset : offset + }; + return zoomToOrFly(this, target, options, false); }; /** @@ -1748,12 +1757,12 @@ Either specify options.terrainProvider instead or set options.baseLayerPicker to * target will be the range. The heading will be determined from the offset. If the heading cannot be * determined from the offset, the heading will be north.

* - * @param {Entity|Entity[]|EntityCollection|DataSource|ImageryLayer|Promise.} target The entity, array of entities, entity collection, data source or imagery layer to view. You can also pass a promise that resolves to one of the previously mentioned types. + * @param {Entity|Entity[]|EntityCollection|DataSource|ImageryLayer|Cesium3DTileset|Promise.} target The entity, array of entities, entity collection, data source, Cesium3DTileset, or imagery layer to view. You can also pass a promise that resolves to one of the previously mentioned types. * @param {Object} [options] Object with the following properties: * @param {Number} [options.duration=3.0] The duration of the flight in seconds. * @param {Number} [options.maximumHeight] The maximum height at the peak of the flight. * @param {HeadingPitchRange} [options.offset] The offset from the target in the local east-north-up reference frame centered at the target. - * @returns {Promise.} A Promise that resolves to true if the flight was successful or false if the entity is not currently visualized in the scene or the flight was cancelled. + * @returns {Promise.} A Promise that resolves to true if the flight was successful or false if the target is not currently visualized in the scene or the flight was cancelled. //TODO: Cleanup entity mentions */ Viewer.prototype.flyTo = function(target, options) { return zoomToOrFly(this, target, options, true); @@ -1794,6 +1803,12 @@ Either specify options.terrainProvider instead or set options.baseLayerPicker to return; } + //If the zoom target is a Cesium3DTileset + if (zoomTarget instanceof Cesium3DTileset) { + that._zoomTarget = zoomTarget; + return; + } + //If the zoom target is a data source, and it's in the middle of loading, wait for it to finish loading. if (zoomTarget.isLoading && defined(zoomTarget.loadingEvent)) { var removeEvent = zoomTarget.loadingEvent.addEventListener(function() { @@ -1821,6 +1836,7 @@ Either specify options.terrainProvider instead or set options.baseLayerPicker to zoomTarget = zoomTarget.entities.values; } + //Zoom target is already an array, just copy it and return. if (isArray(zoomTarget)) { that._zoomTarget = zoomTarget.slice(0); } else { @@ -1855,8 +1871,8 @@ Either specify options.terrainProvider instead or set options.baseLayerPicker to }; function updateZoomTarget(viewer) { - var entities = viewer._zoomTarget; - if (!defined(entities) || viewer.scene.mode === SceneMode.MORPHING) { + var target = viewer._zoomTarget; + if (!defined(target) || viewer.scene.mode === SceneMode.MORPHING) { return; } @@ -1864,11 +1880,47 @@ Either specify options.terrainProvider instead or set options.baseLayerPicker to var camera = scene.camera; var zoomPromise = viewer._zoomPromise; var zoomOptions = defaultValue(viewer._zoomOptions, {}); + var options; + + // If zoomTarget was Cesium3DTileset + if (target instanceof Cesium3DTileset) { + return target.readyPromise.then(function() { + var boundingSphere = target.boundingSphere; + // if offset was originally undefined then give it base value instead of empty object + if (!defined(zoomOptions.offset)) { + zoomOptions.offset = new HeadingPitchRange(0.0, -0.5, boundingSphere.radius); + } + + options = { + offset : zoomOptions.offset, + duration : zoomOptions.duration, + maximumHeight : zoomOptions.maximumHeight, + complete : function() { + zoomPromise.resolve(true); + }, + cancel : function() { + zoomPromise.resolve(false); + } + }; + + if (viewer._zoomIsFlight) { + camera.flyToBoundingSphere(target.boundingSphere, options); + } else { + camera.viewBoundingSphere(boundingSphere, zoomOptions.offset); + camera.lookAtTransform(Matrix4.IDENTITY); + + // finish the promise + zoomPromise.resolve(true); + } + + clearZoom(viewer); + }); + } //If zoomTarget was an ImageryLayer - if (entities instanceof Rectangle) { - var options = { - destination : entities, + if (target instanceof Rectangle) { + options = { + destination : target, duration : zoomOptions.duration, maximumHeight : zoomOptions.maximumHeight, complete : function() { @@ -1889,6 +1941,8 @@ Either specify options.terrainProvider instead or set options.baseLayerPicker to return; } + var entities = target; + var boundingSpheres = []; for (var i = 0, len = entities.length; i < len; i++) { var state = viewer._dataSourceDisplay.getBoundingSphere(entities[i], false, boundingSphereScratch); @@ -1911,7 +1965,7 @@ Either specify options.terrainProvider instead or set options.baseLayerPicker to var boundingSphere = BoundingSphere.fromBoundingSpheres(boundingSpheres); if (!viewer._zoomIsFlight) { - camera.viewBoundingSphere(boundingSphere, viewer._zoomOptions); + camera.viewBoundingSphere(boundingSphere, viewer._zoomOptions.offset); camera.lookAtTransform(Matrix4.IDENTITY); clearZoom(viewer); zoomPromise.resolve(true); diff --git a/Specs/Widgets/Viewer/ViewerSpec.js b/Specs/Widgets/Viewer/ViewerSpec.js index e3b39921df1e..b0d19110ba78 100644 --- a/Specs/Widgets/Viewer/ViewerSpec.js +++ b/Specs/Widgets/Viewer/ViewerSpec.js @@ -1,11 +1,15 @@ defineSuite([ + 'Core/BoundingSphere', 'Core/Cartesian3', 'Core/ClockRange', 'Core/ClockStep', + 'Core/Color', 'Core/EllipsoidTerrainProvider', + 'Core/HeadingPitchRange', 'Core/JulianDate', 'Core/Matrix4', 'Core/WebMercatorProjection', + 'DataSources/BoundingSphereState', 'DataSources/ConstantPositionProperty', 'DataSources/ConstantProperty', 'DataSources/DataSourceClock', @@ -14,6 +18,7 @@ defineSuite([ 'DataSources/Entity', 'Scene/Camera', 'Scene/CameraFlightPath', + 'Scene/Cesium3DTileset', 'Scene/ImageryLayerCollection', 'Scene/SceneMode', 'Scene/ShadowMode', @@ -34,13 +39,17 @@ defineSuite([ 'Widgets/SelectionIndicator/SelectionIndicator', 'Widgets/Timeline/Timeline' ], 'Widgets/Viewer/Viewer', function( + BoundingSphere, Cartesian3, ClockRange, ClockStep, + Color, EllipsoidTerrainProvider, + HeadingPitchRange, JulianDate, Matrix4, WebMercatorProjection, + BoundingSphereState, ConstantPositionProperty, ConstantProperty, DataSourceClock, @@ -49,6 +58,7 @@ defineSuite([ Entity, Camera, CameraFlightPath, + Cesium3DTileset, ImageryLayerCollection, SceneMode, ShadowMode, @@ -727,7 +737,7 @@ defineSuite([ dataSource1.clock.stopTime = JulianDate.fromIso8601('2013-08-21T02:00Z'); dataSource1.clock.currentTime = JulianDate.fromIso8601('2013-08-02T00:00Z'); - viewer = createViewer(container, { automaticallyTrackDataSourceClocks : false }); + viewer = createViewer(container, {automaticallyTrackDataSourceClocks : false}); viewer.dataSources.add(dataSource1); // Because of the above Viewer option, data sources are not automatically @@ -932,7 +942,7 @@ defineSuite([ //Needed to avoid actually creating a flight when we issue the home command. spyOn(CameraFlightPath, 'createTween').and.returnValue({ startObject : {}, - stopObject: {}, + stopObject : {}, duration : 0.0 }); @@ -1021,4 +1031,370 @@ defineSuite([ expect(preMixinDataSource.entities.collectionChanged._listeners.length).not.toEqual(preMixinListenerCount); expect(postMixinDataSource.entities.collectionChanged._listeners.length).not.toEqual(postMixinListenerCount); }); + + it('zoomTo throws if target is not defined', function() { + viewer = createViewer(container); + + expect(function() { + viewer.zoomTo(); + }).toThrowDeveloperError(); + }); + + it('zoomTo zooms to Cesium3DTileset with default offset when offset not defined', function() { + viewer = createViewer(container); + + var path = './Data/Cesium3DTiles/Tilesets/TilesetOfTilesets'; + var tileset = new Cesium3DTileset({ + url : path + }); + + // load the tileset then check tests + return tileset.readyPromise.then(function() { + var expectedBoundingSphere = tileset.boundingSphere; + var expectedOffset = new HeadingPitchRange(0.0, -0.5, expectedBoundingSphere.radius); + + var promise = viewer.zoomTo(tileset); + var wasCompleted = false; + spyOn(viewer.camera, 'viewBoundingSphere').and.callFake(function(boundingSphere, offset) { + expect(boundingSphere).toEqual(expectedBoundingSphere); + expect(offset).toEqual(expectedOffset); + wasCompleted = true; + }); + + viewer.render(); + + return promise.then(function() { + expect(wasCompleted).toEqual(true); + }); + }); + }); + + it('zoomTo zooms to Cesium3DTileset with offset', function() { + viewer = createViewer(container); + + var path = './Data/Cesium3DTiles/Tilesets/TilesetOfTilesets'; + var tileset = new Cesium3DTileset({ + url : path + }); + + // load the tileset then check tests + return tileset.readyPromise.then(function() { + var expectedBoundingSphere = tileset.boundingSphere; + var expectedOffset = new HeadingPitchRange(0.4, 1.2, 4.0 * expectedBoundingSphere.radius); + + var promise = viewer.zoomTo(tileset, expectedOffset); + var wasCompleted = false; + spyOn(viewer.camera, 'viewBoundingSphere').and.callFake(function(boundingSphere, offset) { + expect(boundingSphere).toEqual(expectedBoundingSphere); + expect(offset).toEqual(expectedOffset); + wasCompleted = true; + }); + + viewer.render(); + + return promise.then(function() { + expect(wasCompleted).toEqual(true); + }); + }); + }); + + it('zoomTo zooms to entity with undefined offset when offset not defined', function() { + viewer = createViewer(container); + viewer.entities.add({ + name : 'Blue box', + position : Cartesian3.fromDegrees(-114.0, 40.0, 300000.0), + box : { + dimensions : new Cartesian3(400000.0, 300000.0, 500000.0), + material : Color.BLUE + } + }); + + var entities = viewer.entities; + + var promise = viewer.zoomTo(entities); + var wasCompleted = false; + + spyOn(viewer.camera, 'viewBoundingSphere').and.callFake(function(boundingSphere, offset) { + expect(boundingSphere).toBeDefined(); + // expect offset to be undefined - doesnt use default bc of how zoomTo for entities is set up + expect(offset).toBeUndefined(); + wasCompleted = true; + }); + + viewer.render(); + + return promise.then(function() { + expect(wasCompleted).toEqual(true); + }); + }); + + it('zoomTo zooms to entity with offset', function() { + viewer = createViewer(container); + viewer.entities.add({ + name : 'Blue box', + position : Cartesian3.fromDegrees(-114.0, 40.0, 300000.0), + box : { + dimensions : new Cartesian3(400000.0, 300000.0, 500000.0), + material : Color.BLUE + } + }); + + var entities = viewer.entities; + // fake temp offset + var expectedOffset = new HeadingPitchRange(3.0, 0.2, 2.3); + + var promise = viewer.zoomTo(entities, expectedOffset); + var wasCompleted = false; + spyOn(viewer.camera, 'viewBoundingSphere').and.callFake(function(boundingSphere, offset) { + expect(expectedOffset).toEqual(offset); + wasCompleted = true; + }); + + viewer.render(); + + return promise.then(function() { + expect(wasCompleted).toEqual(true); + }); + }); + + it('flyTo throws if target is not defined', function() { + viewer = createViewer(container); + + expect(function() { + viewer.flyTo(); + }).toThrowDeveloperError(); + }); + + it('flyTo flys to Cesium3DTileset with default offset when options not defined', function() { + viewer = createViewer(container); + + var path = './Data/Cesium3DTiles/Tilesets/TilesetOfTilesets'; + var tileset = new Cesium3DTileset({ + url : path + }); + + // load tileset to test + return tileset.readyPromise.then(function() { + var promise = viewer.flyTo(tileset); + var wasCompleted = false; + + spyOn(viewer.camera, 'flyToBoundingSphere').and.callFake(function(target, options) { + expect(options.offset).toBeDefined(); + expect(options.duration).toBeUndefined(); + expect(options.maximumHeight).toBeUndefined(); + wasCompleted = true; + options.complete(); + }); + + viewer.render(); + + return promise.then(function() { + expect(wasCompleted).toEqual(true); + }); + }); + + }); + + it('flyTo flys to Cesium3DTileset with default offset when offset not defined', function() { + viewer = createViewer(container); + + var path = './Data/Cesium3DTiles/Tilesets/TilesetOfTilesets'; + var tileset = new Cesium3DTileset({ + url : path + }); + + var options = {}; + + // load tileset to test + return tileset.readyPromise.then(function() { + var promise = viewer.flyTo(tileset, options); + var wasCompleted = false; + + spyOn(viewer.camera, 'flyToBoundingSphere').and.callFake(function(target, options) { + expect(options.offset).toBeDefined(); + expect(options.duration).toBeUndefined(); + expect(options.maximumHeight).toBeUndefined(); + wasCompleted = true; + options.complete(); + }); + + viewer.render(); + + return promise.then(function() { + expect(wasCompleted).toEqual(true); + }); + + }); + }); + + it('flyTo flys to target when target is Cesium3DTileset and options are defined', function() { + viewer = createViewer(container); + + var path = './Data/Cesium3DTiles/Tilesets/TilesetOfTilesets'; + var tileset = new Cesium3DTileset({ + url : path + }); + + // load tileset to test + return tileset.readyPromise.then(function() { + var offsetVal = new HeadingPitchRange(3.0, 0.2, 2.3); + var options = { + offset : offsetVal, + duration : 3.0, + maximumHeight : 5.0 + }; + + var promise = viewer.flyTo(tileset, options); + var wasCompleted = false; + + spyOn(viewer.camera, 'flyToBoundingSphere').and.callFake(function(target, options) { + expect(options.duration).toBeDefined(); + expect(options.maximumHeight).toBeDefined(); + wasCompleted = true; + options.complete(); + }); + + viewer.render(); + + return promise.then(function() { + expect(wasCompleted).toEqual(true); + }); + + }); + }); + + it('flyTo flys to entity with default offset when options not defined', function() { + viewer = createViewer(container); + + viewer.entities.add({ + name : 'Blue box', + position : Cartesian3.fromDegrees(-114.0, 40.0, 300000.0), + box : { + dimensions : new Cartesian3(400000.0, 300000.0, 500000.0), + material : Color.BLUE + } + }); + + var entities = viewer.entities; + var promise = viewer.flyTo(entities); + var wasCompleted = false; + + spyOn(viewer.camera, 'flyToBoundingSphere').and.callFake(function(target, options) { + expect(options.duration).toBeUndefined(); + expect(options.maximumHeight).toBeUndefined(); + wasCompleted = true; + options.complete(); + }); + + viewer.render(); + + return promise.then(function() { + expect(wasCompleted).toEqual(true); + }); + + }); + + it('flyTo flys to entity with default offset when offset not defined', function() { + viewer = createViewer(container); + + viewer.entities.add({ + name : 'Blue box', + position : Cartesian3.fromDegrees(-114.0, 40.0, 300000.0), + box : { + dimensions : new Cartesian3(400000.0, 300000.0, 500000.0), + material : Color.BLUE + } + }); + + var entities = viewer.entities; + var options = {}; + + var promise = viewer.flyTo(entities, options); + var wasCompleted = false; + + spyOn(viewer.camera, 'flyToBoundingSphere').and.callFake(function(target, options) { + expect(options.duration).toBeUndefined(); + expect(options.maximumHeight).toBeUndefined(); + wasCompleted = true; + options.complete(); + }); + + viewer.render(); + + return promise.then(function() { + expect(wasCompleted).toEqual(true); + }); + }); + + it('flyTo flys to entity when options are defined', function() { + viewer = createViewer(container); + + viewer.entities.add({ + name : 'Blue box', + position : Cartesian3.fromDegrees(-114.0, 40.0, 300000.0), + box : { + dimensions : new Cartesian3(400000.0, 300000.0, 500000.0), + material : Color.BLUE + } + }); + + var entities = viewer.entities; + var offsetVal = new HeadingPitchRange(3.0, 0.2, 2.3); + var options = { + offset : offsetVal, + duration : 3.0, + maximumHeight : 5.0 + }; + + var promise = viewer.flyTo(entities, options); + var wasCompleted = false; + + spyOn(viewer.camera, 'flyToBoundingSphere').and.callFake(function(target, options) { + expect(options.duration).toBeDefined(); + expect(options.maximumHeight).toBeDefined(); + wasCompleted = true; + options.complete(); + }); + + viewer.render(); + + return promise.then(function() { + expect(wasCompleted).toEqual(true); + }); + }); + + it('flyTo flys to entity when offset is defined but other options for flyTo are not', function() { + viewer = createViewer(container); + + viewer.entities.add({ + name : 'Blue box', + position : Cartesian3.fromDegrees(-114.0, 40.0, 300000.0), + box : { + dimensions : new Cartesian3(400000.0, 300000.0, 500000.0), + material : Color.BLUE + } + }); + + var entities = viewer.entities; + var offsetVal = new HeadingPitchRange(3.0, 0.2, 2.3); + var options = { + offset : offsetVal + }; + + var promise = viewer.flyTo(entities, options); + var wasCompleted = false; + + spyOn(viewer.camera, 'flyToBoundingSphere').and.callFake(function(target, options) { + expect(options.duration).toBeUndefined(); + expect(options.maximumHeight).toBeUndefined(); + wasCompleted = true; + options.complete(); + }); + + viewer.render(); + + return promise.then(function() { + expect(wasCompleted).toEqual(true); + }); + }); }, 'WebGL');