diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index e3577b817566..37cdec736bfd 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -10,7 +10,7 @@ define([ 'Cesium/DataSources/CzmlDataSource', 'Cesium/DataSources/GeoJsonDataSource', 'Cesium/DataSources/KmlDataSource', - 'Cesium/Scene/TileMapServiceImageryProvider', + 'Cesium/Scene/createTileMapServiceImageryProvider', 'Cesium/Widgets/Viewer/Viewer', 'Cesium/Widgets/Viewer/viewerCesiumInspectorMixin', 'Cesium/Widgets/Viewer/viewerDragDropMixin', @@ -26,7 +26,7 @@ define([ CzmlDataSource, GeoJsonDataSource, KmlDataSource, - TileMapServiceImageryProvider, + createTileMapServiceImageryProvider, Viewer, viewerCesiumInspectorMixin, viewerDragDropMixin) { @@ -47,7 +47,7 @@ define([ var imageryProvider; if (endUserOptions.tmsImageryUrl) { - imageryProvider = new TileMapServiceImageryProvider({ + imageryProvider = createTileMapServiceImageryProvider({ url : endUserOptions.tmsImageryUrl }); } diff --git a/Apps/Sandcastle/gallery/Imagery Layers Manipulation.html b/Apps/Sandcastle/gallery/Imagery Layers Manipulation.html index 94960cdbb793..b7b9798daabb 100644 --- a/Apps/Sandcastle/gallery/Imagery Layers Manipulation.html +++ b/Apps/Sandcastle/gallery/Imagery Layers Manipulation.html @@ -139,7 +139,7 @@ })); addBaseLayerOption( 'Natural Earth II (local)', - new Cesium.TileMapServiceImageryProvider({ + Cesium.createTileMapServiceImageryProvider({ url : require.toUrl('Assets/Textures/NaturalEarthII') })); addBaseLayerOption( @@ -181,7 +181,7 @@ })); addAdditionalLayerOption( 'TileMapService Image', - new Cesium.TileMapServiceImageryProvider({ + Cesium.createTileMapServiceImageryProvider({ url : '../images/cesium_maptiler/Cesium_Logo_Color' }), 0.2); diff --git a/Apps/Sandcastle/gallery/Imagery Layers.html b/Apps/Sandcastle/gallery/Imagery Layers.html index 79554ad4e04b..757804bad070 100644 --- a/Apps/Sandcastle/gallery/Imagery Layers.html +++ b/Apps/Sandcastle/gallery/Imagery Layers.html @@ -35,7 +35,7 @@ }); var layers = viewer.imageryLayers; -var blackMarble = layers.addImageryProvider(new Cesium.TileMapServiceImageryProvider({ +var blackMarble = layers.addImageryProvider(Cesium.createTileMapServiceImageryProvider({ url : '//cesiumjs.org/blackmarble', maximumLevel : 8, credit : 'Black Marble imagery courtesy NASA Earth Observatory' diff --git a/CHANGES.md b/CHANGES.md index cc9ac419b3fe..ac13a2c85238 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -14,11 +14,15 @@ Change Log * Removed `HeightmapTessellator` from the public API. It is now private and subject to change without notice. * Removed `TerrainMesh` from the public API. It is now private and subject to change without notice. * Removed `jsonp`. Use `loadJsonp` instead. +* Deprecated + * Deprecated `TileMapServiceImageryProvider`. It will be removed in 1.18. Use `createTileMapServiceImageryProvider` instead. +* Refactored `UrlTemplateImageryProvider.reinitialize` to accept a promise to `options`. * Reduced the amount of both GPU and CPU memory used by terrain. The CPU memory was reduced by up to 40%. * `CorridorGeometry` and `PolylineVolumeGeometry` render short segments [#3293](https://github.com/AnalyticalGraphicsInc/cesium/issues/3293) * `Rectangle.fromCartographicArray` finds the smallest rectangle regardess of whether or not it crosses the international date line. [#3227](https://github.com/AnalyticalGraphicsInc/cesium/issues/3227) * Bug fix for `CorridorGeometry` with nearly colinear points [#3320](https://github.com/AnalyticalGraphicsInc/cesium/issues/3320) + ### 1.16 - 2015-12-01 * Deprecated diff --git a/Source/Core/CesiumTerrainProvider.js b/Source/Core/CesiumTerrainProvider.js index e32f4346caaf..7928404910a0 100644 --- a/Source/Core/CesiumTerrainProvider.js +++ b/Source/Core/CesiumTerrainProvider.js @@ -79,7 +79,7 @@ define([ * * // Terrain geometry near the surface of the globe is difficult to view when using NaturalEarthII imagery, * // unless the TerrainProvider provides additional lighting information to shade the terrain (as shown above). - * var imageryProvider = new Cesium.TileMapServiceImageryProvider({ + * var imageryProvider = Cesium.createTileMapServiceImageryProvider({ * url : 'http://localhost:8080/Source/Assets/Textures/NaturalEarthII', * fileExtension : 'jpg' * }); diff --git a/Source/Scene/ArcGisMapServerImageryProvider.js b/Source/Scene/ArcGisMapServerImageryProvider.js index 55455e2fa5f1..20471850cf08 100644 --- a/Source/Scene/ArcGisMapServerImageryProvider.js +++ b/Source/Scene/ArcGisMapServerImageryProvider.js @@ -97,7 +97,7 @@ define([ * @see GoogleEarthImageryProvider * @see createOpenStreetMapImageryProvider * @see SingleTileImageryProvider - * @see TileMapServiceImageryProvider + * @see createTileMapServiceImageryProvider * @see WebMapServiceImageryProvider * @see WebMapTileServiceImageryProvider * @see UrlTemplateImageryProvider diff --git a/Source/Scene/BingMapsImageryProvider.js b/Source/Scene/BingMapsImageryProvider.js index 1bf8337b393d..bfa3e571742c 100644 --- a/Source/Scene/BingMapsImageryProvider.js +++ b/Source/Scene/BingMapsImageryProvider.js @@ -79,7 +79,7 @@ define([ * @see GoogleEarthImageryProvider * @see createOpenStreetMapImageryProvider * @see SingleTileImageryProvider - * @see TileMapServiceImageryProvider + * @see createTileMapServiceImageryProvider * @see WebMapServiceImageryProvider * @see WebMapTileServiceImageryProvider * @see UrlTemplateImageryProvider diff --git a/Source/Scene/GoogleEarthImageryProvider.js b/Source/Scene/GoogleEarthImageryProvider.js index 201b9a723802..049cfd8fe528 100644 --- a/Source/Scene/GoogleEarthImageryProvider.js +++ b/Source/Scene/GoogleEarthImageryProvider.js @@ -84,7 +84,7 @@ define([ * @see BingMapsImageryProvider * @see createOpenStreetMapImageryProvider * @see SingleTileImageryProvider - * @see TileMapServiceImageryProvider + * @see createTileMapServiceImageryProvider * @see WebMapServiceImageryProvider * @see WebMapTileServiceImageryProvider * @see UrlTemplateImageryProvider @@ -591,4 +591,3 @@ define([ return GoogleEarthImageryProvider; }); - diff --git a/Source/Scene/ImageryProvider.js b/Source/Scene/ImageryProvider.js index 74994e657e4a..abbd46cf974d 100644 --- a/Source/Scene/ImageryProvider.js +++ b/Source/Scene/ImageryProvider.js @@ -233,7 +233,8 @@ define([ * include an alpha channel. If this property is false, an alpha channel, if present, will * be ignored. If this property is true, any images without an alpha channel will be treated * as if their alpha is 1.0 everywhere. When this property is false, memory usage - * and texture upload time are reduced. + * and texture upload time are reduced. This function should + * not be called before {@link ImageryProvider#ready} returns true. * @memberof ImageryProvider.prototype * @type {Boolean} * @readonly diff --git a/Source/Scene/OpenStreetMapImageryProvider.js b/Source/Scene/OpenStreetMapImageryProvider.js index 0bc20da0367b..7f4d17740385 100644 --- a/Source/Scene/OpenStreetMapImageryProvider.js +++ b/Source/Scene/OpenStreetMapImageryProvider.js @@ -51,7 +51,7 @@ define([ * @see BingMapsImageryProvider * @see GoogleEarthImageryProvider * @see SingleTileImageryProvider - * @see TileMapServiceImageryProvider + * @see createTileMapServiceImageryProvider * @see WebMapServiceImageryProvider * @see WebMapTileServiceImageryProvider * @see UrlTemplateImageryProvider @@ -64,7 +64,7 @@ define([ * var osm = new Cesium.OpenStreetMapImageryProvider({ * url : '//a.tile.openstreetmap.org/' * }); - * + * * @deprecated */ function OpenStreetMapImageryProvider(options) { diff --git a/Source/Scene/SingleTileImageryProvider.js b/Source/Scene/SingleTileImageryProvider.js index 601377cba6e2..cf115512c209 100644 --- a/Source/Scene/SingleTileImageryProvider.js +++ b/Source/Scene/SingleTileImageryProvider.js @@ -45,7 +45,7 @@ define([ * @see BingMapsImageryProvider * @see GoogleEarthImageryProvider * @see createOpenStreetMapImageryProvider - * @see TileMapServiceImageryProvider + * @see createTileMapServiceImageryProvider * @see WebMapServiceImageryProvider * @see WebMapTileServiceImageryProvider * @see UrlTemplateImageryProvider diff --git a/Source/Scene/TileMapServiceImageryProvider.js b/Source/Scene/TileMapServiceImageryProvider.js index 6b3c405fc7c9..eec7d7ddffb1 100644 --- a/Source/Scene/TileMapServiceImageryProvider.js +++ b/Source/Scene/TileMapServiceImageryProvider.js @@ -6,6 +6,7 @@ define([ '../Core/defaultValue', '../Core/defined', '../Core/defineProperties', + '../Core/deprecationWarning', '../Core/DeveloperError', '../Core/Event', '../Core/GeographicTilingScheme', @@ -24,6 +25,7 @@ define([ defaultValue, defined, defineProperties, + deprecationWarning, DeveloperError, Event, GeographicTilingScheme, @@ -34,10 +36,13 @@ define([ TileProviderError, WebMercatorTilingScheme, when, - ImageryProvider) { + ImageryProvider + ) { "use strict"; /** + * @deprecated + * * Provides tiled imagery as generated by {@link http://www.maptiler.org/'>MapTiler / >includeStart('debug', pragmas.debug); diff --git a/Source/Scene/UrlTemplateImageryProvider.js b/Source/Scene/UrlTemplateImageryProvider.js index d0a5251daad6..33298251a667 100644 --- a/Source/Scene/UrlTemplateImageryProvider.js +++ b/Source/Scene/UrlTemplateImageryProvider.js @@ -54,7 +54,7 @@ define([ * @constructor * * @param {Object} [options] Object with the following properties: - * @param {String} [options.url] The URL template to use to request tiles. It has the following keywords: + * @param {String} options.url The URL template to use to request tiles. It has the following keywords: *
{z}
: The level of the tile in the tiling scheme. Level zero is the root of the quadtree pyramid.{x}
: The tile X coordinate in the tiling scheme, where 0 is the Westernmost tile.{height}
: The height of each tile in pixels.url
* parameter, plus the following:
* {latitudeDegrees}
: The latitude of the picked position in degrees.{longitudeProjected}
: The longitude of the picked position in the projected coordinates of the tiling scheme.{latitudeProjected}
: The latitude of the picked position in the projected coordinates of the tiling scheme.{format}
: The format in which to get feature information, as specified in the {@see GetFeatureInfoFormat}.{format}
: The format in which to get feature information, as specified in the {@link GetFeatureInfoFormat}.{s}
placeholder in the URL template.
* If this parameter is a single string, each character in the string is a subdomain. If it is
@@ -113,15 +113,14 @@ define([
* be treated as if their alpha is 1.0 everywhere. When this property is false, memory usage
* and texture upload time are potentially reduced.
* @param {GetFeatureInfoFormat[]} [options.getFeatureInfoFormats] The formats in which to get feature information at a
- * specific location when {@see UrlTemplateImageryProvider#pickFeatures} is invoked. If this
+ * specific location when {@link UrlTemplateImageryProvider#pickFeatures} is invoked. If this
* parameter is not specified, feature picking is disabled.
- *
* @see ArcGisMapServerImageryProvider
* @see BingMapsImageryProvider
* @see GoogleEarthImageryProvider
* @see createOpenStreetMapImageryProvider
* @see SingleTileImageryProvider
- * @see TileMapServiceImageryProvider
+ * @see createTileMapServiceImageryProvider
* @see WebMapServiceImageryProvider
* @see WebMapTileServiceImageryProvider
*
@@ -151,47 +150,71 @@ define([
*/
function UrlTemplateImageryProvider(options) {
//>>includeStart('debug', pragmas.debug);
- if (!defined(options) || !defined(options.url)) {
- throw new DeveloperError('options.url is required.');
+ if (!defined(options)) {
+ throw new DeveloperError('options is required.');
+ }
+ if (!when.isPromise(options) && !defined(options.url)) {
+ throw new DeveloperError('options is required.');
}
//>>includeEnd('debug');
- this._url = options.url;
- this._pickFeaturesUrl = options.pickFeaturesUrl;
- this._proxy = options.proxy;
- this._tileDiscardPolicy = options.tileDiscardPolicy;
- this._getFeatureInfoFormats = options.getFeatureInfoFormats;
-
this._errorEvent = new Event();
- this._subdomains = options.subdomains;
- if (Array.isArray(this._subdomains)) {
- this._subdomains = this._subdomains.slice();
- } else if (defined(this._subdomains) && this._subdomains.length > 0) {
- this._subdomains = this._subdomains.split('');
- } else {
- this._subdomains = ['a', 'b', 'c'];
- }
+ this._url = undefined;
+ this._pickFeaturesUrl = undefined;
+ this._proxy = undefined;
+ this._tileWidth = undefined;
+ this._tileHeight = undefined;
+ this._maximumLevel = undefined;
+ this._minimumLevel = undefined;
+ this._tilingScheme = undefined;
+ this._rectangle = undefined;
+ this._tileDiscardPolicy = undefined;
+ this._credit = undefined;
+ this._hasAlphaChannel = undefined;
- this._tileWidth = defaultValue(options.tileWidth, 256);
- this._tileHeight = defaultValue(options.tileHeight, 256);
- this._minimumLevel = defaultValue(options.minimumLevel, 0);
- this._maximumLevel = options.maximumLevel;
- this._tilingScheme = defaultValue(options.tilingScheme, new WebMercatorTilingScheme({ ellipsoid : options.ellipsoid }));
- this._rectangle = defaultValue(options.rectangle, this._tilingScheme.rectangle);
- this._rectangle = Rectangle.intersection(this._rectangle, this._tilingScheme.rectangle);
- this._hasAlphaChannel = defaultValue(options.hasAlphaChannel, true);
-
- var credit = options.credit;
- if (typeof credit === 'string') {
- credit = new Credit(credit);
- }
- this._credit = credit;
+ var that = this;
+ this._readyPromise = when(options).then(function(properties) {
+ //>>includeStart('debug', pragmas.debug);
+ if (!defined(properties.url)) {
+ throw new DeveloperError('options.url is required.');
+ }
+ //>>includeEnd('debug');
+
+ that._url = properties.url;
+ that._pickFeaturesUrl = properties.pickFeaturesUrl;
+ that._proxy = properties.proxy;
+ that._tileDiscardPolicy = properties.tileDiscardPolicy;
+ that._getFeatureInfoFormats = properties.getFeatureInfoFormats;
+
+ that._subdomains = properties.subdomains;
+ if (Array.isArray(that._subdomains)) {
+ that._subdomains = that._subdomains.slice();
+ } else if (defined(that._subdomains) && that._subdomains.length > 0) {
+ that._subdomains = that._subdomains.split('');
+ } else {
+ that._subdomains = ['a', 'b', 'c'];
+ }
- this._urlParts = urlTemplateToParts(this._url, tags);
- this._pickFeaturesUrlParts = urlTemplateToParts(this._pickFeaturesUrl, pickFeaturesTags);
+ that._tileWidth = defaultValue(properties.tileWidth, 256);
+ that._tileHeight = defaultValue(properties.tileHeight, 256);
+ that._minimumLevel = defaultValue(properties.minimumLevel, 0);
+ that._maximumLevel = properties.maximumLevel;
+ that._tilingScheme = defaultValue(properties.tilingScheme, new WebMercatorTilingScheme({ ellipsoid : properties.ellipsoid }));
+ that._rectangle = defaultValue(properties.rectangle, that._tilingScheme.rectangle);
+ that._rectangle = Rectangle.intersection(that._rectangle, that._tilingScheme.rectangle);
+ that._hasAlphaChannel = defaultValue(properties.hasAlphaChannel, true);
+
+ var credit = properties.credit;
+ if (typeof credit === 'string') {
+ credit = new Credit(credit);
+ }
+ that._credit = credit;
- this._readyPromise = when.resolve(true);
+ that._urlParts = urlTemplateToParts(that._url, tags);
+ that._pickFeaturesUrlParts = urlTemplateToParts(that._pickFeaturesUrl, pickFeaturesTags);
+ return true;
+ });
}
defineProperties(UrlTemplateImageryProvider.prototype, {
@@ -274,6 +297,11 @@ define([
*/
tileWidth : {
get : function() {
+ //>>includeStart('debug', pragmas.debug);
+ if (!this.ready) {
+ throw new DeveloperError('tileWidth must not be called before the imagery provider is ready.');
+ }
+ //>>includeEnd('debug');
return this._tileWidth;
}
},
@@ -288,6 +316,11 @@ define([
*/
tileHeight: {
get : function() {
+ //>>includeStart('debug', pragmas.debug);
+ if (!this.ready) {
+ throw new DeveloperError('tileHeight must not be called before the imagery provider is ready.');
+ }
+ //>>includeEnd('debug');
return this._tileHeight;
}
},
@@ -302,6 +335,11 @@ define([
*/
maximumLevel : {
get : function() {
+ //>>includeStart('debug', pragmas.debug);
+ if (!this.ready) {
+ throw new DeveloperError('maximumLevel must not be called before the imagery provider is ready.');
+ }
+ //>>includeEnd('debug');
return this._maximumLevel;
}
},
@@ -316,6 +354,11 @@ define([
*/
minimumLevel : {
get : function() {
+ //>>includeStart('debug', pragmas.debug);
+ if (!this.ready) {
+ throw new DeveloperError('minimumLevel must not be called before the imagery provider is ready.');
+ }
+ //>>includeEnd('debug');
return this._minimumLevel;
}
},
@@ -330,6 +373,11 @@ define([
*/
tilingScheme : {
get : function() {
+ //>>includeStart('debug', pragmas.debug);
+ if (!this.ready) {
+ throw new DeveloperError('tilingScheme must not be called before the imagery provider is ready.');
+ }
+ //>>includeEnd('debug');
return this._tilingScheme;
}
},
@@ -344,6 +392,11 @@ define([
*/
rectangle : {
get : function() {
+ //>>includeStart('debug', pragmas.debug);
+ if (!this.ready) {
+ throw new DeveloperError('rectangle must not be called before the imagery provider is ready.');
+ }
+ //>>includeEnd('debug');
return this._rectangle;
}
},
@@ -360,6 +413,11 @@ define([
*/
tileDiscardPolicy : {
get : function() {
+ //>>includeStart('debug', pragmas.debug);
+ if (!this.ready) {
+ throw new DeveloperError('tileDiscardPolicy must not be called before the imagery provider is ready.');
+ }
+ //>>includeEnd('debug');
return this._tileDiscardPolicy;
}
},
@@ -386,7 +444,7 @@ define([
*/
ready : {
get : function() {
- return true;
+ return defined(this._urlParts);
}
},
@@ -412,6 +470,11 @@ define([
*/
credit : {
get : function() {
+ //>>includeStart('debug', pragmas.debug);
+ if (!this.ready) {
+ throw new DeveloperError('credit must not be called before the imagery provider is ready.');
+ }
+ //>>includeEnd('debug');
return this._credit;
}
},
@@ -421,7 +484,8 @@ define([
* include an alpha channel. If this property is false, an alpha channel, if present, will
* be ignored. If this property is true, any images without an alpha channel will be treated
* as if their alpha is 1.0 everywhere. When this property is false, memory usage
- * and texture upload time are reduced.
+ * and texture upload time are reduced. This function should
+ * not be called before {@link ImageryProvider#ready} returns true.
* @memberof UrlTemplateImageryProvider.prototype
* @type {Boolean}
* @readonly
@@ -429,6 +493,11 @@ define([
*/
hasAlphaChannel : {
get : function() {
+ //>>includeStart('debug', pragmas.debug);
+ if (!this.ready) {
+ throw new DeveloperError('hasAlphaChannel must not be called before the imagery provider is ready.');
+ }
+ //>>includeEnd('debug');
return this._hasAlphaChannel;
}
}
@@ -445,6 +514,11 @@ define([
* @exception {DeveloperError} getTileCredits
must not be called before the imagery provider is ready.
*/
UrlTemplateImageryProvider.prototype.getTileCredits = function(x, y, level) {
+ //>>includeStart('debug', pragmas.debug);
+ if (!this.ready) {
+ throw new DeveloperError('getTileCredits must not be called before the imagery provider is ready.');
+ }
+ //>>includeEnd('debug');
return undefined;
};
@@ -461,6 +535,11 @@ define([
* Image or a Canvas DOM object.
*/
UrlTemplateImageryProvider.prototype.requestImage = function(x, y, level) {
+ //>>includeStart('debug', pragmas.debug);
+ if (!this.ready) {
+ throw new DeveloperError('requestImage must not be called before the imagery provider is ready.');
+ }
+ //>>includeEnd('debug');
var url = buildImageUrl(this, x, y, level);
return ImageryProvider.loadImage(this, url);
};
@@ -480,6 +559,12 @@ define([
* It may also be undefined if picking is not supported.
*/
UrlTemplateImageryProvider.prototype.pickFeatures = function(x, y, level, longitude, latitude) {
+ //>>includeStart('debug', pragmas.debug);
+ if (!this.ready) {
+ throw new DeveloperError('pickFeatures must not be called before the imagery provider is ready.');
+ }
+ //>>includeEnd('debug');
+
if (!defined(this._pickFeaturesUrl) || this._getFeatureInfoFormats.length === 0) {
return undefined;
}
diff --git a/Source/Scene/WebMapServiceImageryProvider.js b/Source/Scene/WebMapServiceImageryProvider.js
index fd70162937b8..f9e9362651ad 100644
--- a/Source/Scene/WebMapServiceImageryProvider.js
+++ b/Source/Scene/WebMapServiceImageryProvider.js
@@ -73,7 +73,7 @@ define([
* @see GoogleEarthImageryProvider
* @see createOpenStreetMapImageryProvider
* @see SingleTileImageryProvider
- * @see TileMapServiceImageryProvider
+ * @see createTileMapServiceImageryProvider
* @see WebMapTileServiceImageryProvider
* @see UrlTemplateImageryProvider
*
diff --git a/Source/Scene/WebMapTileServiceImageryProvider.js b/Source/Scene/WebMapTileServiceImageryProvider.js
index 2e48c58494d6..b629cd016e3d 100644
--- a/Source/Scene/WebMapTileServiceImageryProvider.js
+++ b/Source/Scene/WebMapTileServiceImageryProvider.js
@@ -65,7 +65,7 @@ define([
* @see GoogleEarthImageryProvider
* @see createOpenStreetMapImageryProvider
* @see SingleTileImageryProvider
- * @see TileMapServiceImageryProvider
+ * @see createTileMapServiceImageryProvider
* @see WebMapServiceImageryProvider
* @see UrlTemplateImageryProvider
*
diff --git a/Source/Scene/createOpenStreetMapImageryProvider.js b/Source/Scene/createOpenStreetMapImageryProvider.js
index cb555e10a55b..5db9837e06fe 100644
--- a/Source/Scene/createOpenStreetMapImageryProvider.js
+++ b/Source/Scene/createOpenStreetMapImageryProvider.js
@@ -43,7 +43,7 @@ define([
* @see BingMapsImageryProvider
* @see GoogleEarthImageryProvider
* @see SingleTileImageryProvider
- * @see TileMapServiceImageryProvider
+ * @see createTileMapServiceImageryProvider
* @see WebMapServiceImageryProvider
* @see WebMapTileServiceImageryProvider
* @see UrlTemplateImageryProvider
diff --git a/Source/Scene/createTileMapServiceImageryProvider.js b/Source/Scene/createTileMapServiceImageryProvider.js
new file mode 100644
index 000000000000..5a2c6edfaee2
--- /dev/null
+++ b/Source/Scene/createTileMapServiceImageryProvider.js
@@ -0,0 +1,288 @@
+/*global define*/
+define([
+ '../Core/appendForwardSlash',
+ '../Core/Cartesian2',
+ '../Core/Cartographic',
+ '../Core/Credit',
+ '../Core/defaultValue',
+ '../Core/defined',
+ '../Core/defineProperties',
+ '../Core/DeveloperError',
+ '../Core/Event',
+ '../Core/GeographicTilingScheme',
+ '../Core/joinUrls',
+ '../Core/loadXML',
+ '../Core/Rectangle',
+ '../Core/RuntimeError',
+ '../Core/TileProviderError',
+ '../Core/WebMercatorTilingScheme',
+ '../ThirdParty/when',
+ './UrlTemplateImageryProvider'
+ ], function(
+ appendForwardSlash,
+ Cartesian2,
+ Cartographic,
+ Credit,
+ defaultValue,
+ defined,
+ defineProperties,
+ DeveloperError,
+ Event,
+ GeographicTilingScheme,
+ joinUrls,
+ loadXML,
+ Rectangle,
+ RuntimeError,
+ TileProviderError,
+ WebMercatorTilingScheme,
+ when,
+ UrlTemplateImageryProvider) {
+ "use strict";
+
+ /**
+ * Creates a {@link UrlTemplateImageryProvider} instance that provides tiled imagery as generated by
+ * {@link http://www.maptiler.org/'>MapTiler / >includeStart('debug', pragmas.debug);
+ if (!defined(options.url)) {
+ throw new DeveloperError('options.url is required.');
+ }
+ //>>includeEnd('debug');
+
+ var url = appendForwardSlash(options.url);
+
+ var deferred = when.defer();
+ var imageryProvider = new UrlTemplateImageryProvider(deferred.promise);
+
+ var metadataError;
+
+ function metadataSuccess(xml) {
+ var tileFormatRegex = /tileformat/i;
+ var tileSetRegex = /tileset/i;
+ var tileSetsRegex = /tilesets/i;
+ var bboxRegex = /boundingbox/i;
+ var srsRegex = /srs/i;
+ var format, bbox, tilesets, srs;
+ var tilesetsList = []; //list of TileSets
+
+ // Allowing options properties (already copied to that) to override XML values
+
+ // Iterate XML Document nodes for properties
+ var nodeList = xml.childNodes[0].childNodes;
+ for (var i = 0; i < nodeList.length; i++){
+ if (tileFormatRegex.test(nodeList.item(i).nodeName)) {
+ format = nodeList.item(i);
+ } else if (tileSetsRegex.test(nodeList.item(i).nodeName)) {
+ tilesets = nodeList.item(i); // Node list of TileSets
+ var tileSetNodes = nodeList.item(i).childNodes;
+ // Iterate the nodes to find all TileSets
+ for(var j = 0; j < tileSetNodes.length; j++) {
+ if (tileSetRegex.test(tileSetNodes.item(j).nodeName)) {
+ // Add them to tilesets list
+ tilesetsList.push(tileSetNodes.item(j));
+ }
+ }
+ } else if (bboxRegex.test(nodeList.item(i).nodeName)) {
+ bbox = nodeList.item(i);
+ } else if (srsRegex.test(nodeList.item(i).nodeName)) {
+ srs = nodeList.item(i).textContent;
+ }
+ }
+
+ var fileExtension = defaultValue(options.fileExtension, format.getAttribute('extension'));
+ var tileWidth = defaultValue(options.tileWidth, parseInt(format.getAttribute('width'), 10));
+ var tileHeight = defaultValue(options.tileHeight, parseInt(format.getAttribute('height'), 10));
+ var minimumLevel = defaultValue(options.minimumLevel, parseInt(tilesetsList[0].getAttribute('order'), 10));
+ var maximumLevel = defaultValue(options.maximumLevel, parseInt(tilesetsList[tilesetsList.length - 1].getAttribute('order'), 10));
+
+ // Determine based on the profile attribute if this tileset was generated by gdal2tiles.py ('mercator' or 'geodetic' profile, in which
+ // case X is latitude and Y is longitude) or by a tool compliant with the TMS standard ('global-mercator' or 'global-geodetic' profile,
+ // in which case X is longitude and Y is latitude).
+ var tilingSchemeName = tilesets.getAttribute('profile');
+
+ var flipXY = false;
+ if (tilingSchemeName === 'geodetic' || tilingSchemeName === 'mercator') {
+ flipXY = true;
+ }
+
+ var tilingScheme = options.tilingScheme;
+
+ if (!defined(tilingScheme)) {
+ if (tilingSchemeName === 'geodetic' || tilingSchemeName === 'global-geodetic') {
+ tilingScheme = new GeographicTilingScheme({ ellipsoid : options.ellipsoid });
+ } else if (tilingSchemeName === 'mercator' || tilingSchemeName === 'global-mercator') {
+ tilingScheme = new WebMercatorTilingScheme({ ellipsoid : options.ellipsoid });
+ } else {
+ var message = joinUrls(url, 'tilemapresource.xml') + 'specifies an unsupported profile attribute, ' + tilingSchemeName + '.';
+ metadataError = TileProviderError.handleError(metadataError, imageryProvider, imageryProvider.errorEvent, message, undefined, undefined, undefined, requestMetadata);
+ if(!metadataError.retry) {
+ deferred.reject(new RuntimeError(message));
+ }
+ return;
+ }
+ }
+
+ // rectangle handling
+ var rectangle = Rectangle.clone(options.rectangle);
+
+ if (!defined(rectangle)) {
+ var swXY;
+ var neXY;
+ var sw;
+ var ne;
+
+ if (flipXY) {
+ swXY = new Cartesian2(parseFloat(bbox.getAttribute('miny')), parseFloat(bbox.getAttribute('minx')));
+ neXY = new Cartesian2(parseFloat(bbox.getAttribute('maxy')), parseFloat(bbox.getAttribute('maxx')));
+
+ // In old tilers with X/Y flipped, coordinate are always geodetic degrees.
+ sw = Cartographic.fromDegrees(swXY.x, swXY.y);
+ ne = Cartographic.fromDegrees(neXY.x, neXY.y);
+ } else {
+ swXY = new Cartesian2(parseFloat(bbox.getAttribute('minx')), parseFloat(bbox.getAttribute('miny')));
+ neXY = new Cartesian2(parseFloat(bbox.getAttribute('maxx')), parseFloat(bbox.getAttribute('maxy')));
+
+ if (tilingScheme instanceof GeographicTilingScheme) {
+ sw = Cartographic.fromDegrees(swXY.x, swXY.y);
+ ne = Cartographic.fromDegrees(neXY.x, neXY.y);
+ } else {
+ var projection = tilingScheme.projection;
+ sw = projection.unproject(swXY);
+ ne = projection.unproject(neXY);
+ }
+ }
+
+ rectangle = new Rectangle(sw.longitude, sw.latitude, ne.longitude, ne.latitude);
+ }
+
+ // The rectangle must not be outside the bounds allowed by the tiling scheme.
+ if (rectangle.west < tilingScheme.rectangle.west) {
+ rectangle.west = tilingScheme.rectangle.west;
+ }
+ if (rectangle.east > tilingScheme.rectangle.east) {
+ rectangle.east = tilingScheme.rectangle.east;
+ }
+ if (rectangle.south < tilingScheme.rectangle.south) {
+ rectangle.south = tilingScheme.rectangle.south;
+ }
+ if (rectangle.north > tilingScheme.rectangle.north) {
+ rectangle.north = tilingScheme.rectangle.north;
+ }
+
+ // Check the number of tiles at the minimum level. If it's more than four,
+ // try requesting the lower levels anyway, 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) {
+ minimumLevel = 0;
+ }
+
+ var templateUrl = url + '{z}/{x}/{reverseY}.' + fileExtension;
+
+ deferred.resolve({
+ url : templateUrl,
+ tilingScheme : tilingScheme,
+ rectangle : rectangle,
+ tileWidth : tileWidth,
+ tileHeight : tileHeight,
+ minimumLevel : minimumLevel,
+ maximumLevel : maximumLevel,
+ proxy : options.proxy,
+ tileDiscardPolicy : options.tileDiscardPolicy,
+ credit: options.credit
+ });
+ }
+
+ function metadataFailure(error) {
+ // Can't load XML, still allow options and defaults
+ var fileExtension = defaultValue(options.fileExtension, 'png');
+ var tileWidth = defaultValue(options.tileWidth, 256);
+ var tileHeight = defaultValue(options.tileHeight, 256);
+ var minimumLevel = defaultValue(options.minimumLevel, 0);
+ var maximumLevel = options.maximumLevel;
+ var tilingScheme = defined(options.tilingScheme) ? options.tilingScheme : new WebMercatorTilingScheme({ ellipsoid : options.ellipsoid });
+ var rectangle = defaultValue(options.rectangle, tilingScheme.rectangle);
+
+ var templateUrl = url + '{z}/{x}/{reverseY}.' + fileExtension;
+
+ deferred.resolve({
+ url : templateUrl,
+ tilingScheme : tilingScheme,
+ rectangle : rectangle,
+ tileWidth : tileWidth,
+ tileHeight : tileHeight,
+ minimumLevel : minimumLevel,
+ maximumLevel : maximumLevel,
+ proxy : options.proxy,
+ tileDiscardPolicy : options.tileDiscardPolicy,
+ credit: options.credit
+ });
+ }
+
+ function requestMetadata() {
+ var resourceUrl = url + 'tilemapresource.xml';
+ var proxy = options.proxy;
+ if (defined(proxy)) {
+ resourceUrl = proxy.getURL(resourceUrl);
+ }
+ // Try to load remaining parameters from XML
+ when(loadXML(resourceUrl), metadataSuccess, metadataFailure);
+ }
+
+ requestMetadata();
+ return imageryProvider;
+ }
+
+ return createTileMapServiceImageryProvider;
+});
diff --git a/Source/Widgets/BaseLayerPicker/BaseLayerPicker.js b/Source/Widgets/BaseLayerPicker/BaseLayerPicker.js
index c4675d990b07..041451151efe 100644
--- a/Source/Widgets/BaseLayerPicker/BaseLayerPicker.js
+++ b/Source/Widgets/BaseLayerPicker/BaseLayerPicker.js
@@ -75,7 +75,7 @@ define([
* tooltip : 'The lights of cities and villages trace the outlines of civilization \
* in this global view of the Earth at night as seen by NASA/NOAA\'s Suomi NPP satellite.',
* creationFunction : function() {
- * return new Cesium.TileMapServiceImageryProvider({
+ * return Cesium.createTileMapServiceImageryProvider({
* url : '//cesiumjs.org/blackmarble',
* maximumLevel : 8,
* credit : 'Black Marble imagery courtesy NASA Earth Observatory'
@@ -88,7 +88,7 @@ define([
* iconUrl : Cesium.buildModuleUrl('Widgets/Images/ImageryProviders/naturalEarthII.png'),
* tooltip : 'Natural Earth II, darkened for contrast.\nhttp://www.naturalearthdata.com/',
* creationFunction : function() {
- * return new Cesium.TileMapServiceImageryProvider({
+ * return Cesium.createTileMapServiceImageryProvider({
* url : Cesium.buildModuleUrl('Assets/Textures/NaturalEarthII')
* });
* }
diff --git a/Source/Widgets/BaseLayerPicker/createDefaultImageryProviderViewModels.js b/Source/Widgets/BaseLayerPicker/createDefaultImageryProviderViewModels.js
index c5340fd341b3..92f6f33ac597 100644
--- a/Source/Widgets/BaseLayerPicker/createDefaultImageryProviderViewModels.js
+++ b/Source/Widgets/BaseLayerPicker/createDefaultImageryProviderViewModels.js
@@ -6,7 +6,7 @@ define([
'../../Scene/BingMapsStyle',
'../../Scene/MapboxImageryProvider',
'../../Scene/createOpenStreetMapImageryProvider',
- '../../Scene/TileMapServiceImageryProvider',
+ '../../Scene/createTileMapServiceImageryProvider',
'../BaseLayerPicker/ProviderViewModel'
], function(
buildModuleUrl,
@@ -15,7 +15,7 @@ define([
BingMapsStyle,
MapboxImageryProvider,
createOpenStreetMapImageryProvider,
- TileMapServiceImageryProvider,
+ createTileMapServiceImageryProvider,
ProviderViewModel) {
"use strict";
@@ -198,7 +198,7 @@ map of the world.\nhttp://www.openstreetmap.org',
tooltip : 'The lights of cities and villages trace the outlines of civilization in this global view of the \
Earth at night as seen by NASA/NOAA\'s Suomi NPP satellite.',
creationFunction : function() {
- return new TileMapServiceImageryProvider({
+ return createTileMapServiceImageryProvider({
url : '//cesiumjs.org/blackmarble',
maximumLevel : 8,
credit : 'Black Marble imagery courtesy NASA Earth Observatory'
@@ -211,7 +211,7 @@ Earth at night as seen by NASA/NOAA\'s Suomi NPP satellite.',
iconUrl : buildModuleUrl('Widgets/Images/ImageryProviders/naturalEarthII.png'),
tooltip : 'Natural Earth II, darkened for contrast.\nhttp://www.naturalearthdata.com/',
creationFunction : function() {
- return new TileMapServiceImageryProvider({
+ return createTileMapServiceImageryProvider({
url : buildModuleUrl('Assets/Textures/NaturalEarthII')
});
}
@@ -221,4 +221,4 @@ Earth at night as seen by NASA/NOAA\'s Suomi NPP satellite.',
}
return createDefaultImageryProviderViewModels;
-});
\ No newline at end of file
+});
diff --git a/Specs/Scene/ImageryLayerSpec.js b/Specs/Scene/ImageryLayerSpec.js
index 41b4a5dd38ef..e5668584a23c 100644
--- a/Specs/Scene/ImageryLayerSpec.js
+++ b/Specs/Scene/ImageryLayerSpec.js
@@ -17,7 +17,7 @@ defineSuite([
'Scene/NeverTileDiscardPolicy',
'Scene/QuadtreeTile',
'Scene/SingleTileImageryProvider',
- 'Scene/TileMapServiceImageryProvider',
+ 'Scene/createTileMapServiceImageryProvider',
'Scene/WebMapServiceImageryProvider',
'Specs/createContext',
'Specs/createFrameState',
@@ -40,7 +40,7 @@ defineSuite([
NeverTileDiscardPolicy,
QuadtreeTile,
SingleTileImageryProvider,
- TileMapServiceImageryProvider,
+ createTileMapServiceImageryProvider,
WebMapServiceImageryProvider,
createContext,
createFrameState,
@@ -239,7 +239,7 @@ defineSuite([
describe('createTileImagerySkeletons', function() {
it('handles a base layer that does not cover the entire globe', function() {
- var provider = new TileMapServiceImageryProvider({
+ var provider = createTileMapServiceImageryProvider({
url : 'Data/TMS/SmallArea'
});
@@ -288,7 +288,7 @@ defineSuite([
url : 'Data/Images/Blue.png'
});
- var provider = new TileMapServiceImageryProvider({
+ var provider = createTileMapServiceImageryProvider({
url : 'Data/TMS/SmallArea'
});
@@ -334,7 +334,7 @@ defineSuite([
url : 'Data/Images/Green4x4.png'
});
- var provider = new TileMapServiceImageryProvider({
+ var provider = createTileMapServiceImageryProvider({
url : 'Data/TMS/SmallArea'
});
diff --git a/Specs/Scene/UrlTemplateImageryProviderSpec.js b/Specs/Scene/UrlTemplateImageryProviderSpec.js
index 03056bcb88a8..c7d32253855f 100644
--- a/Specs/Scene/UrlTemplateImageryProviderSpec.js
+++ b/Specs/Scene/UrlTemplateImageryProviderSpec.js
@@ -547,4 +547,76 @@ defineSuite([
expect(provider.pickFeatures(0, 0, 0, 0.0, 0.0)).toBeUndefined();
});
});
+
+ it('throws if tileWidth called before provider is ready', function() {
+ var provider = new UrlTemplateImageryProvider(when.defer());
+
+ expect(function() {
+ return provider.tileWidth();
+ }).toThrowDeveloperError();
+ });
+
+ it('throws if tileHeight called before provider is ready', function() {
+ var provider = new UrlTemplateImageryProvider(when.defer());
+
+ expect(function() {
+ return provider.tileHeight();
+ }).toThrowDeveloperError();
+ });
+
+ it('throws if maximumLevel called before provider is ready', function() {
+ var provider = new UrlTemplateImageryProvider(when.defer());
+
+ expect(function() {
+ return provider.maximumLevel();
+ }).toThrowDeveloperError();
+ });
+
+ it('throws if minimumLevel called before provider is ready', function() {
+ var provider = new UrlTemplateImageryProvider(when.defer());
+
+ expect(function() {
+ return provider.minimumLevel();
+ }).toThrowDeveloperError();
+ });
+
+ it('throws if tilingScheme called before provider is ready', function() {
+ var provider = new UrlTemplateImageryProvider(when.defer());
+
+ expect(function() {
+ return provider.tilingScheme();
+ }).toThrowDeveloperError();
+ });
+
+ it('throws if rectangle called before provider is ready', function() {
+ var provider = new UrlTemplateImageryProvider(when.defer());
+
+ expect(function() {
+ return provider.rectangle();
+ }).toThrowDeveloperError();
+ });
+
+ it('throws if tileDiscardPolicy called before provider is ready', function() {
+ var provider = new UrlTemplateImageryProvider(when.defer());
+
+ expect(function() {
+ return provider.tileDiscardPolicy();
+ }).toThrowDeveloperError();
+ });
+
+ it('throws if credit called before provider is ready', function() {
+ var provider = new UrlTemplateImageryProvider(when.defer());
+
+ expect(function() {
+ return provider.credit();
+ }).toThrowDeveloperError();
+ });
+
+ it('throws if hasAlphaChannel called before provider is ready', function() {
+ var provider = new UrlTemplateImageryProvider(when.defer());
+
+ expect(function() {
+ return provider.hasAlphaChannel();
+ }).toThrowDeveloperError();
+ });
});
diff --git a/Specs/Scene/createTileMapServiceImageryProviderSpec.js b/Specs/Scene/createTileMapServiceImageryProviderSpec.js
new file mode 100644
index 000000000000..b9d2f42a015e
--- /dev/null
+++ b/Specs/Scene/createTileMapServiceImageryProviderSpec.js
@@ -0,0 +1,709 @@
+/*global defineSuite*/
+defineSuite([
+ 'Scene/createTileMapServiceImageryProvider',
+ 'Core/Cartesian2',
+ 'Core/Cartographic',
+ 'Core/DefaultProxy',
+ 'Core/defined',
+ 'Core/GeographicProjection',
+ 'Core/GeographicTilingScheme',
+ 'Core/loadImage',
+ 'Core/loadWithXhr',
+ 'Core/Math',
+ 'Core/Rectangle',
+ 'Core/WebMercatorProjection',
+ 'Core/WebMercatorTilingScheme',
+ 'Scene/Imagery',
+ 'Scene/ImageryLayer',
+ 'Scene/UrlTemplateImageryProvider',
+ 'Scene/ImageryState',
+ 'Specs/pollToPromise',
+ 'ThirdParty/when'
+ ], function(
+ createTileMapServiceImageryProvider,
+ Cartesian2,
+ Cartographic,
+ DefaultProxy,
+ defined,
+ GeographicProjection,
+ GeographicTilingScheme,
+ loadImage,
+ loadWithXhr,
+ CesiumMath,
+ Rectangle,
+ WebMercatorProjection,
+ WebMercatorTilingScheme,
+ Imagery,
+ ImageryLayer,
+ UrlTemplateImageryProvider,
+ ImageryState,
+ pollToPromise,
+ when) {
+ "use strict";
+
+ afterEach(function() {
+ loadImage.createImage = loadImage.defaultCreateImage;
+ loadWithXhr.load = loadWithXhr.defaultLoad;
+ });
+
+ it('return a UrlTemplateImageryProvider', function() {
+ var provider = createTileMapServiceImageryProvider({
+ url: 'made/up/tms/server/'
+ });
+ expect(provider).toBeInstanceOf(UrlTemplateImageryProvider);
+ });
+
+ it('resolves readyPromise', function() {
+ var provider = createTileMapServiceImageryProvider({
+ url : 'made/up/tms/server/'
+ });
+
+ return provider.readyPromise.then(function(result) {
+ expect(result).toBe(true);
+ expect(provider.ready).toBe(true);
+ });
+ });
+
+ it('rejects readyPromise on error', function() {
+ loadWithXhr.load = function(url, responseType, method, data, headers, deferred, overrideMimeType) {
+ // We can't resolve the promise immediately, because then the error would be raised
+ // before we could subscribe to it. This a problem particular to tests.
+ setTimeout(function() {
+ var parser = new DOMParser();
+ var xmlString =
+ '