diff --git a/Apps/Sandcastle/gallery/Imagery Layers Manipulation.html b/Apps/Sandcastle/gallery/Imagery Layers Manipulation.html index 9dd9f56ab96b..94960cdbb793 100644 --- a/Apps/Sandcastle/gallery/Imagery Layers Manipulation.html +++ b/Apps/Sandcastle/gallery/Imagery Layers Manipulation.html @@ -124,15 +124,15 @@ })); addBaseLayerOption( 'OpenStreetMaps', - new Cesium.OpenStreetMapImageryProvider()); + Cesium.createOpenStreetMapImageryProvider()); addBaseLayerOption( 'MapQuest OpenStreetMaps', - new Cesium.OpenStreetMapImageryProvider({ + Cesium.createOpenStreetMapImageryProvider({ url: '//otile1-s.mqcdn.com/tiles/1.0.0/osm/' })); addBaseLayerOption( 'Stamen Maps', - new Cesium.OpenStreetMapImageryProvider({ + Cesium.createOpenStreetMapImageryProvider({ url: '//stamen-tiles.a.ssl.fastly.net/watercolor/', fileExtension: 'jpg', credit: 'Map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under CC BY SA.' diff --git a/CHANGES.md b/CHANGES.md index c4c6ae2d1a24..d73f00e02aee 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,6 +3,8 @@ Change Log ### 1.16 - 2015-12-01 +* Deprecated + * Deprecated `OpenStreetMapImageryProvider`. It will be removed in 1.18. Use `createOpenStreetMapImageryProvider` instead. * Fixed an issue where the sun texture is not generated correctly on some mobile devices. [#3141](https://github.com/AnalyticalGraphicsInc/cesium/issues/3141) * Fixed a bug in the deprecated `jsonp` that prevented it from returning a promise. Its replacement, `loadJsonp`, was unaffected. * Fixed glTF implementation to read the version as a string as per the specification and to correctly handle backwards compatibility for axis-angle rotations in glTF 0.8 models. @@ -28,6 +30,7 @@ Change Log * `Material` image uniforms now accept and `HTMLVideoElement` anywhere it could previously take a `Canvas` element. * Added `VideoSynchronizer` helper object for keeping an `HTMLVideoElement` in sync with a scene's clock. * Added 'Video' Sandcastle showcase to demonstrate video materials. +* Added `createOpenStreetMapImageryProvider` function to replace the `OpenStreetMapImageryProvider` class. This function returns a constructed `UrlTemplateImageryProvider`. * Fixed an issue with tile selection when below the surface of the ellipsoid. [#3170](https://github.com/AnalyticalGraphicsInc/cesium/issues/3170) ### 1.15 - 2015-11-02 diff --git a/Source/Scene/ArcGisMapServerImageryProvider.js b/Source/Scene/ArcGisMapServerImageryProvider.js index a4646ab698eb..b33237690ab0 100644 --- a/Source/Scene/ArcGisMapServerImageryProvider.js +++ b/Source/Scene/ArcGisMapServerImageryProvider.js @@ -95,7 +95,7 @@ define([ * * @see BingMapsImageryProvider * @see GoogleEarthImageryProvider - * @see OpenStreetMapImageryProvider + * @see createOpenStreetMapImageryProvider * @see SingleTileImageryProvider * @see TileMapServiceImageryProvider * @see WebMapServiceImageryProvider diff --git a/Source/Scene/BingMapsImageryProvider.js b/Source/Scene/BingMapsImageryProvider.js index 55efd9d0a941..1dd2d760645d 100644 --- a/Source/Scene/BingMapsImageryProvider.js +++ b/Source/Scene/BingMapsImageryProvider.js @@ -77,7 +77,7 @@ define([ * * @see ArcGisMapServerImageryProvider * @see GoogleEarthImageryProvider - * @see OpenStreetMapImageryProvider + * @see createOpenStreetMapImageryProvider * @see SingleTileImageryProvider * @see TileMapServiceImageryProvider * @see WebMapServiceImageryProvider diff --git a/Source/Scene/GoogleEarthImageryProvider.js b/Source/Scene/GoogleEarthImageryProvider.js index 736942848349..dbd3c28f4bf1 100644 --- a/Source/Scene/GoogleEarthImageryProvider.js +++ b/Source/Scene/GoogleEarthImageryProvider.js @@ -82,7 +82,7 @@ define([ * * @see ArcGisMapServerImageryProvider * @see BingMapsImageryProvider - * @see OpenStreetMapImageryProvider + * @see createOpenStreetMapImageryProvider * @see SingleTileImageryProvider * @see TileMapServiceImageryProvider * @see WebMapServiceImageryProvider diff --git a/Source/Scene/ImageryProvider.js b/Source/Scene/ImageryProvider.js index 59aeade6062e..77ddad6d710c 100644 --- a/Source/Scene/ImageryProvider.js +++ b/Source/Scene/ImageryProvider.js @@ -27,7 +27,7 @@ define([ * @see BingMapsImageryProvider * @see GoogleEarthImageryProvider * @see MapboxImageryProvider - * @see OpenStreetMapImageryProvider + * @see createOpenStreetMapImageryProvider * @see WebMapTileServiceImageryProvider * @see WebMapServiceImageryProvider * diff --git a/Source/Scene/OpenStreetMapImageryProvider.js b/Source/Scene/OpenStreetMapImageryProvider.js index d7610ea758cc..db8ec9999c67 100644 --- a/Source/Scene/OpenStreetMapImageryProvider.js +++ b/Source/Scene/OpenStreetMapImageryProvider.js @@ -4,6 +4,7 @@ define([ '../Core/defaultValue', '../Core/defined', '../Core/defineProperties', + '../Core/deprecationWarning', '../Core/DeveloperError', '../Core/Event', '../Core/Rectangle', @@ -15,6 +16,7 @@ define([ defaultValue, defined, defineProperties, + deprecationWarning, DeveloperError, Event, Rectangle, @@ -62,8 +64,11 @@ define([ * var osm = new Cesium.OpenStreetMapImageryProvider({ * url : '//a.tile.openstreetmap.org/' * }); + * + * @deprecated */ var OpenStreetMapImageryProvider = function OpenStreetMapImageryProvider(options) { + deprecationWarning('OpenStreetMapImageryProvider', 'OpenStreetMapImageryProvider is deprecated. It will be removed in Cesium 1.18. Use createOpenStreetMapImageryProvider instead.'); options = defaultValue(options, {}); var url = defaultValue(options.url, '//a.tile.openstreetmap.org/'); diff --git a/Source/Scene/SingleTileImageryProvider.js b/Source/Scene/SingleTileImageryProvider.js index 7bdb44ee8d7e..0409279750a0 100644 --- a/Source/Scene/SingleTileImageryProvider.js +++ b/Source/Scene/SingleTileImageryProvider.js @@ -44,7 +44,7 @@ define([ * @see ArcGisMapServerImageryProvider * @see BingMapsImageryProvider * @see GoogleEarthImageryProvider - * @see OpenStreetMapImageryProvider + * @see createOpenStreetMapImageryProvider * @see TileMapServiceImageryProvider * @see WebMapServiceImageryProvider * @see WebMapTileServiceImageryProvider diff --git a/Source/Scene/TileMapServiceImageryProvider.js b/Source/Scene/TileMapServiceImageryProvider.js index 8233fcb7a975..cbdcc6fb1c56 100644 --- a/Source/Scene/TileMapServiceImageryProvider.js +++ b/Source/Scene/TileMapServiceImageryProvider.js @@ -65,7 +65,7 @@ define([ * @see ArcGisMapServerImageryProvider * @see BingMapsImageryProvider * @see GoogleEarthImageryProvider - * @see OpenStreetMapImageryProvider + * @see createOpenStreetMapImageryProvider * @see SingleTileImageryProvider * @see WebMapServiceImageryProvider * @see WebMapTileServiceImageryProvider diff --git a/Source/Scene/UrlTemplateImageryProvider.js b/Source/Scene/UrlTemplateImageryProvider.js index 8e874bdd3ff0..b9ace4dadc7b 100644 --- a/Source/Scene/UrlTemplateImageryProvider.js +++ b/Source/Scene/UrlTemplateImageryProvider.js @@ -119,7 +119,7 @@ define([ * @see ArcGisMapServerImageryProvider * @see BingMapsImageryProvider * @see GoogleEarthImageryProvider - * @see OpenStreetMapImageryProvider + * @see createOpenStreetMapImageryProvider * @see SingleTileImageryProvider * @see TileMapServiceImageryProvider * @see WebMapServiceImageryProvider diff --git a/Source/Scene/WebMapServiceImageryProvider.js b/Source/Scene/WebMapServiceImageryProvider.js index f2dc96d83a3f..3808f7c5b0f4 100644 --- a/Source/Scene/WebMapServiceImageryProvider.js +++ b/Source/Scene/WebMapServiceImageryProvider.js @@ -73,7 +73,7 @@ define([ * @see ArcGisMapServerImageryProvider * @see BingMapsImageryProvider * @see GoogleEarthImageryProvider - * @see OpenStreetMapImageryProvider + * @see createOpenStreetMapImageryProvider * @see SingleTileImageryProvider * @see TileMapServiceImageryProvider * @see WebMapTileServiceImageryProvider diff --git a/Source/Scene/WebMapTileServiceImageryProvider.js b/Source/Scene/WebMapTileServiceImageryProvider.js index a1492d6d9e96..9d2712f4045d 100644 --- a/Source/Scene/WebMapTileServiceImageryProvider.js +++ b/Source/Scene/WebMapTileServiceImageryProvider.js @@ -63,7 +63,7 @@ define([ * @see ArcGisMapServerImageryProvider * @see BingMapsImageryProvider * @see GoogleEarthImageryProvider - * @see OpenStreetMapImageryProvider + * @see createOpenStreetMapImageryProvider * @see SingleTileImageryProvider * @see TileMapServiceImageryProvider * @see WebMapServiceImageryProvider diff --git a/Source/Scene/createOpenStreetMapImageryProvider.js b/Source/Scene/createOpenStreetMapImageryProvider.js new file mode 100644 index 000000000000..e7289779cce7 --- /dev/null +++ b/Source/Scene/createOpenStreetMapImageryProvider.js @@ -0,0 +1,111 @@ +/*global define*/ +define([ + '../Core/Credit', + '../Core/defaultValue', + '../Core/DeveloperError', + '../Core/Rectangle', + '../Core/WebMercatorTilingScheme', + './UrlTemplateImageryProvider' +], function( + Credit, + defaultValue, + DeveloperError, + Rectangle, + WebMercatorTilingScheme, + UrlTemplateImageryProvider +) { + "use strict"; + + var trailingSlashRegex = /\/$/; + var defaultCredit = new Credit('MapQuest, Open Street Map and contributors, CC-BY-SA'); + + /** + * Creates a {@link UrlTemplateImageryProvider} instance that provides tiled imagery hosted by OpenStreetMap + * or another provider of Slippy tiles. The default url connects to OpenStreetMap's volunteer-run + * servers, so you must conform to their + * {@link http://wiki.openstreetmap.org/wiki/Tile_usage_policy|Tile Usage Policy}. + * + * @exports createOpenStreetMapImageryProvider + * + * @param {Object} [options] Object with the following properties: + * @param {String} [options.url='//a.tile.openstreetmap.org'] The OpenStreetMap server url. + * @param {String} [options.fileExtension='png'] The file extension for images on the server. + * @param {Object} [options.proxy] A proxy to use for requests. This object is expected to have a getURL function which returns the proxied URL. + * @param {Rectangle} [options.rectangle=Rectangle.MAX_VALUE] The rectangle of the layer. + * @param {Number} [options.minimumLevel=0] The minimum level-of-detail supported by the imagery provider. + * @param {Number} [options.maximumLevel] The maximum level-of-detail supported by the imagery provider, or undefined if there is no limit. + * @param {Ellipsoid} [options.ellipsoid] The ellipsoid. If not specified, the WGS84 ellipsoid is used. + * @param {Credit|String} [options.credit='MapQuest, Open Street Map and contributors, CC-BY-SA'] A credit for the data source, which is displayed on the canvas. + * + * @exception {DeveloperError} The rectangle and minimumLevel indicate that there are more than four tiles at the minimum level. Imagery providers with more than four tiles at the minimum level are not supported. + * + * @see ArcGisMapServerImageryProvider + * @see BingMapsImageryProvider + * @see GoogleEarthImageryProvider + * @see SingleTileImageryProvider + * @see TileMapServiceImageryProvider + * @see WebMapServiceImageryProvider + * @see WebMapTileServiceImageryProvider + * @see UrlTemplateImageryProvider + * + * @see {@link http://wiki.openstreetmap.org/wiki/Main_Page|OpenStreetMap Wiki} + * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing} + * + * @example + * var osm = Cesium.createOpenStreetMapImageryProvider({ + * url : '//a.tile.openstreetmap.org/' + * }); + */ + var createOpenStreetMapImageryProvider = function createOpenStreetMapImageryProvider(options) { + options = defaultValue(options, {}); + + var url = defaultValue(options.url, '//a.tile.openstreetmap.org/'); + + if (!trailingSlashRegex.test(url)) { + url = url + '/'; + } + + var fileExtension = defaultValue(options.fileExtension, 'png'); + + var tilingScheme = new WebMercatorTilingScheme({ ellipsoid : options.ellipsoid }); + + var tileWidth = 256; + var tileHeight = 256; + + var minimumLevel = defaultValue(options.minimumLevel, 0); + var maximumLevel = options.maximumLevel; + + var rectangle = defaultValue(options.rectangle, tilingScheme.rectangle); + + // Check the number of tiles at the minimum level. If it's more than four, + // throw an exception, because starting at the higher minimum + // level will cause too many tiles to be downloaded and rendered. + var swTile = tilingScheme.positionToTileXY(Rectangle.southwest(rectangle), minimumLevel); + var neTile = tilingScheme.positionToTileXY(Rectangle.northeast(rectangle), minimumLevel); + var tileCount = (Math.abs(neTile.x - swTile.x) + 1) * (Math.abs(neTile.y - swTile.y) + 1); + if (tileCount > 4) { + throw new DeveloperError('The rectangle and minimumLevel indicate that there are ' + tileCount + ' tiles at the minimum level. Imagery providers with more than four tiles at the minimum level are not supported.'); + } + + var credit = defaultValue(options.credit, defaultCredit); + if (typeof credit === 'string') { + credit = new Credit(credit); + } + + var templateUrl = url + "{z}/{x}/{y}." + fileExtension; + + return new UrlTemplateImageryProvider({ + url: templateUrl, + proxy: options.proxy, + credit: credit, + tilingScheme: tilingScheme, + tileWidth: tileWidth, + tileHeight: tileHeight, + minimumLevel: minimumLevel, + maximumLevel: maximumLevel, + rectangle: rectangle + }); + }; + + return createOpenStreetMapImageryProvider; +}); \ No newline at end of file diff --git a/Source/Widgets/BaseLayerPicker/BaseLayerPicker.js b/Source/Widgets/BaseLayerPicker/BaseLayerPicker.js index d56897bba743..13fe8c6ccc8f 100644 --- a/Source/Widgets/BaseLayerPicker/BaseLayerPicker.js +++ b/Source/Widgets/BaseLayerPicker/BaseLayerPicker.js @@ -63,7 +63,7 @@ define([ * tooltip : 'OpenStreetMap (OSM) is a collaborative project to create a free editable \ * map of the world.\nhttp://www.openstreetmap.org', * creationFunction : function() { - * return new Cesium.OpenStreetMapImageryProvider({ + * return Cesium.createOpenStreetMapImageryProvider({ * url : '//a.tile.openstreetmap.org/' * }); * } diff --git a/Source/Widgets/BaseLayerPicker/createDefaultImageryProviderViewModels.js b/Source/Widgets/BaseLayerPicker/createDefaultImageryProviderViewModels.js index 96edc645c3e8..c5340fd341b3 100644 --- a/Source/Widgets/BaseLayerPicker/createDefaultImageryProviderViewModels.js +++ b/Source/Widgets/BaseLayerPicker/createDefaultImageryProviderViewModels.js @@ -5,7 +5,7 @@ define([ '../../Scene/BingMapsImageryProvider', '../../Scene/BingMapsStyle', '../../Scene/MapboxImageryProvider', - '../../Scene/OpenStreetMapImageryProvider', + '../../Scene/createOpenStreetMapImageryProvider', '../../Scene/TileMapServiceImageryProvider', '../BaseLayerPicker/ProviderViewModel' ], function( @@ -14,7 +14,7 @@ define([ BingMapsImageryProvider, BingMapsStyle, MapboxImageryProvider, - OpenStreetMapImageryProvider, + createOpenStreetMapImageryProvider, TileMapServiceImageryProvider, ProviderViewModel) { "use strict"; @@ -149,7 +149,7 @@ mapping applications.\nhttp://www.esri.com', tooltip : 'OpenStreetMap (OSM) is a collaborative project to create a free editable map \ of the world.\nhttp://www.openstreetmap.org', creationFunction : function() { - return new OpenStreetMapImageryProvider({ + return createOpenStreetMapImageryProvider({ url : '//a.tile.openstreetmap.org/' }); } @@ -161,7 +161,7 @@ of the world.\nhttp://www.openstreetmap.org', tooltip : 'Reminiscent of hand drawn maps, Stamen watercolor maps apply raster effect \ area washes and organic edges over a paper texture to add warm pop to any map.\nhttp://maps.stamen.com', creationFunction : function() { - return new OpenStreetMapImageryProvider({ + return createOpenStreetMapImageryProvider({ url : '//stamen-tiles.a.ssl.fastly.net/watercolor/', credit : 'Map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under CC BY SA.' }); @@ -173,7 +173,7 @@ area washes and organic edges over a paper texture to add warm pop to any map.\n iconUrl : buildModuleUrl('Widgets/Images/ImageryProviders/stamenToner.png'), tooltip : 'A high contrast black and white map.\nhttp://maps.stamen.com', creationFunction : function() { - return new OpenStreetMapImageryProvider({ + return createOpenStreetMapImageryProvider({ url : '//stamen-tiles.a.ssl.fastly.net/toner/', credit : 'Map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under CC BY SA.' }); @@ -186,7 +186,7 @@ area washes and organic edges over a paper texture to add warm pop to any map.\n tooltip : 'OpenStreetMap (OSM) is a collaborative project to create a free editable \ map of the world.\nhttp://www.openstreetmap.org', creationFunction : function() { - return new OpenStreetMapImageryProvider({ + return createOpenStreetMapImageryProvider({ url : '//otile1-s.mqcdn.com/tiles/1.0.0/osm/' }); } diff --git a/Source/Widgets/CesiumWidget/CesiumWidget.js b/Source/Widgets/CesiumWidget/CesiumWidget.js index 24511e23b132..3dccc622191d 100644 --- a/Source/Widgets/CesiumWidget/CesiumWidget.js +++ b/Source/Widgets/CesiumWidget/CesiumWidget.js @@ -168,7 +168,7 @@ define([ * * //Widget with OpenStreetMaps imagery provider and Cesium terrain provider hosted by AGI. * var widget = new Cesium.CesiumWidget('cesiumContainer', { - * imageryProvider : new Cesium.OpenStreetMapImageryProvider(), + * imageryProvider : Cesium.createOpenStreetMapImageryProvider(), * terrainProvider : new Cesium.CesiumTerrainProvider({ * url : '//assets.agi.com/stk-terrain/world' * }), diff --git a/Source/Widgets/Viewer/Viewer.js b/Source/Widgets/Viewer/Viewer.js index edf54b8353a1..2ca5f54fb81a 100644 --- a/Source/Widgets/Viewer/Viewer.js +++ b/Source/Widgets/Viewer/Viewer.js @@ -250,7 +250,7 @@ define([ * //Hide the base layer picker * baseLayerPicker : false, * //Use OpenStreetMaps - * imageryProvider : new Cesium.OpenStreetMapImageryProvider({ + * imageryProvider : Cesium.createOpenStreetMapImageryProvider({ * url : '//a.tile.openstreetmap.org/' * }), * // Use high-res stars downloaded from https://github.com/AnalyticalGraphicsInc/cesium-assets diff --git a/Specs/Scene/createOpenStreetMapImageryProviderSpec.js b/Specs/Scene/createOpenStreetMapImageryProviderSpec.js new file mode 100644 index 000000000000..0ff77d4435c5 --- /dev/null +++ b/Specs/Scene/createOpenStreetMapImageryProviderSpec.js @@ -0,0 +1,269 @@ +/*global defineSuite*/ +defineSuite([ + 'Scene/createOpenStreetMapImageryProvider', + 'Core/DefaultProxy', + 'Core/loadImage', + 'Core/Math', + 'Core/Rectangle', + 'Core/WebMercatorTilingScheme', + 'Scene/Imagery', + 'Scene/ImageryLayer', + 'Scene/ImageryProvider', + 'Scene/ImageryState', + 'Specs/pollToPromise', + 'Scene/UrlTemplateImageryProvider', +], function( + createOpenStreetMapImageryProvider, + DefaultProxy, + loadImage, + CesiumMath, + Rectangle, + WebMercatorTilingScheme, + Imagery, + ImageryLayer, + ImageryProvider, + ImageryState, + pollToPromise, + UrlTemplateImageryProvider) { + "use strict"; + + afterEach(function() { + loadImage.createImage = loadImage.defaultCreateImage; + }); + + it('return a UrlTemplateImageryProvider', function() { + var provider = createOpenStreetMapImageryProvider(); + expect(provider).toBeInstanceOf(UrlTemplateImageryProvider); + }); + + it('returns valid value for hasAlphaChannel', function() { + var provider = createOpenStreetMapImageryProvider({ + url : 'made/up/osm/server/' + }); + + return pollToPromise(function() { + return provider.ready; + }).then(function() { + expect(typeof provider.hasAlphaChannel).toBe('boolean'); + }); + }); + + it('supports a slash at the end of the URL', function() { + var provider = createOpenStreetMapImageryProvider({ + url : 'made/up/osm/server/' + }); + + return pollToPromise(function() { + return provider.ready; + }).then(function() { + spyOn(loadImage, 'createImage').and.callFake(function(url, crossOrigin, deferred) { + expect(url).not.toContain('//'); + + // Just return any old image. + loadImage.defaultCreateImage('Data/Images/Red16x16.png', crossOrigin, deferred); + }); + + return provider.requestImage(0, 0, 0).then(function(image) { + expect(loadImage.createImage).toHaveBeenCalled(); + expect(image).toBeInstanceOf(Image); + }); + }); + }); + + it('supports no slash at the endof the URL', function() { + var provider = createOpenStreetMapImageryProvider({ + url : 'made/up/osm/server' + }); + + return pollToPromise(function() { + return provider.ready; + }).then(function() { + spyOn(loadImage, 'createImage').and.callFake(function(url, crossOrigin, deferred) { + expect(url).toContain('made/up/osm/server/'); + + // Just return any old image. + loadImage.defaultCreateImage('Data/Images/Red16x16.png', crossOrigin, deferred); + }); + + return provider.requestImage(0, 0, 0).then(function(image) { + expect(loadImage.createImage).toHaveBeenCalled(); + expect(image).toBeInstanceOf(Image); + }); + }); + }); + + it('requestImage returns a promise for an image and loads it for cross-origin use', function() { + var provider = createOpenStreetMapImageryProvider({ + url : 'made/up/osm/server/' + }); + + expect(provider.url).toContain('made/up/osm/server/'); + + return pollToPromise(function() { + return provider.ready; + }).then(function() { + expect(provider.tileWidth).toEqual(256); + expect(provider.tileHeight).toEqual(256); + expect(provider.maximumLevel).toBeUndefined(); + expect(provider.tilingScheme).toBeInstanceOf(WebMercatorTilingScheme); + expect(provider.rectangle).toEqual(new WebMercatorTilingScheme().rectangle); + + spyOn(loadImage, 'createImage').and.callFake(function(url, crossOrigin, deferred) { + // Just return any old image. + loadImage.defaultCreateImage('Data/Images/Red16x16.png', crossOrigin, deferred); + }); + + return provider.requestImage(0, 0, 0).then(function(image) { + expect(loadImage.createImage).toHaveBeenCalled(); + expect(image).toBeInstanceOf(Image); + }); + }); + }); + + it('when no credit is supplied, a default one is used', function() { + var provider = createOpenStreetMapImageryProvider({ + url : 'made/up/osm/server' + }); + expect(provider.credit).toBeDefined(); + }); + + it('turns the supplied credit into a logo', function() { + var providerWithCredit = createOpenStreetMapImageryProvider({ + url : 'made/up/osm/server', + credit : 'Thanks to our awesome made up source of this imagery!' + }); + expect(providerWithCredit.credit).toBeDefined(); + }); + + it('routes requests through a proxy if one is specified', function() { + var proxy = new DefaultProxy('/proxy/'); + var provider = createOpenStreetMapImageryProvider({ + url : 'made/up/osm/server', + proxy : proxy + }); + + return pollToPromise(function() { + return provider.ready; + }).then(function() { + expect(provider.proxy).toEqual(proxy); + + spyOn(loadImage, 'createImage').and.callFake(function(url, crossOrigin, deferred) { + expect(url.indexOf(proxy.getURL('made/up/osm/server'))).toEqual(0); + + // Just return any old image. + loadImage.defaultCreateImage('Data/Images/Red16x16.png', crossOrigin, deferred); + }); + + return provider.requestImage(0, 0, 0).then(function(image) { + expect(loadImage.createImage).toHaveBeenCalled(); + expect(image).toBeInstanceOf(Image); + }); + }); + }); + + it('rectangle passed to constructor does not affect tile numbering', function() { + var rectangle = new Rectangle(0.1, 0.2, 0.3, 0.4); + var provider = createOpenStreetMapImageryProvider({ + url : 'made/up/osm/server', + rectangle : rectangle + }); + + return pollToPromise(function() { + return provider.ready; + }).then(function() { + expect(provider.tileWidth).toEqual(256); + expect(provider.tileHeight).toEqual(256); + expect(provider.maximumLevel).toBeUndefined(); + expect(provider.tilingScheme).toBeInstanceOf(WebMercatorTilingScheme); + expect(provider.rectangle.west).toBeCloseTo(rectangle.west, CesiumMath.EPSILON10); + expect(provider.rectangle.south).toBeCloseTo(rectangle.south, CesiumMath.EPSILON10); + expect(provider.rectangle.east).toBeCloseTo(rectangle.east, CesiumMath.EPSILON10); + expect(provider.rectangle.north).toBeCloseTo(rectangle.north, CesiumMath.EPSILON10); + expect(provider.tileDiscardPolicy).toBeUndefined(); + + spyOn(loadImage, 'createImage').and.callFake(function(url, crossOrigin, deferred) { + expect(url).toContain('/0/0/0'); + + // Just return any old image. + loadImage.defaultCreateImage('Data/Images/Red16x16.png', crossOrigin, deferred); + }); + + return provider.requestImage(0, 0, 0).then(function(image) { + expect(loadImage.createImage).toHaveBeenCalled(); + expect(image).toBeInstanceOf(Image); + }); + }); + }); + + it('uses maximumLevel passed to constructor', function() { + var provider = createOpenStreetMapImageryProvider({ + url : 'made/up/osm/server', + maximumLevel : 5 + }); + expect(provider.maximumLevel).toEqual(5); + }); + + it('uses minimumLevel passed to constructor', function() { + var provider = createOpenStreetMapImageryProvider({ + url : 'made/up/osm/server', + minimumLevel : 1 + }); + expect(provider.minimumLevel).toEqual(1); + }); + + it('raises error event when image cannot be loaded', function() { + var provider = createOpenStreetMapImageryProvider({ + url : 'made/up/osm/server' + }); + + var layer = new ImageryLayer(provider); + + var tries = 0; + provider.errorEvent.addEventListener(function(error) { + expect(error.timesRetried).toEqual(tries); + ++tries; + if (tries < 3) { + error.retry = true; + } + }); + + loadImage.createImage = function(url, crossOrigin, deferred) { + if (tries === 2) { + // Succeed after 2 tries + loadImage.defaultCreateImage('Data/Images/Red16x16.png', crossOrigin, deferred); + } else { + // fail + setTimeout(function() { + deferred.reject(); + }, 1); + } + }; + + return pollToPromise(function() { + return provider.ready; + }).then(function() { + var imagery = new Imagery(layer, 0, 0, 0); + imagery.addReference(); + layer._requestImagery(imagery); + + return pollToPromise(function() { + return imagery.state === ImageryState.RECEIVED; + }).then(function() { + expect(imagery.image).toBeInstanceOf(Image); + expect(tries).toEqual(2); + imagery.releaseReference(); + }); + }); + }); + + it('throws with more than four tiles at the minimum', function() { + var rectangle = new Rectangle(0.0, 0.0, CesiumMath.toRadians(1.0), CesiumMath.toRadians(1.0)); + + expect(function() { + return createOpenStreetMapImageryProvider({ + minimumLevel : 9, + rectangle : rectangle + }); + }).toThrowDeveloperError(); + }); +});