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 1cbe08b09224..f5f1aa3d9476 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,6 +7,7 @@ Change Log * Removed support for `CESIUM_binary_glTF`. Use `KHR_binary_glTF` instead. * Deprecated * Deprecated `GroundPrimitive.geometryInstance`. It will be removed in 1.20. Use `GroundPrimitive.geometryInstances` instead. + * Deprecated `TileMapServiceImageryProvider`. It will be removed in 1.20. Use `createTileMapServiceImageryProvider` instead. * Reduced the amount of CPU memory used by terrain by ~25% in Chrome. * Fixed a picking problem ([#3386](https://github.com/AnalyticalGraphicsInc/cesium/issues/3386)) that sometimes prevented objects being selected. * Added `Scene.useDepthPicking` to enable or disable picking using the depth buffer. [#3390](https://github.com/AnalyticalGraphicsInc/cesium/pull/3390) @@ -26,6 +27,8 @@ Change Log * Fixed creating bounding volumes for `GroundPrimitive`s whose containing rectangle has a width greater than pi. * Fixed incorrect texture coordinates for polygons with large height. * Fixed camera.flyTo not working when in 2D mode and only orientation changes +* Added `UrlTemplateImageryProvider.reinitialize` for changing imagery provider options without creating a new instance. +* `UrlTemplateImageryProvider` now accepts a promise to an `options` object in addition to taking the object directly. ### 1.17 - 2016-01-04 diff --git a/Source/Core/CesiumTerrainProvider.js b/Source/Core/CesiumTerrainProvider.js index d7f88933253d..5f704e45ec10 100644 --- a/Source/Core/CesiumTerrainProvider.js +++ b/Source/Core/CesiumTerrainProvider.js @@ -78,7 +78,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 = new 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 6cf1f31dfc46..bfb97fb6dab1 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 b606cee9539b..32cf5602f3a5 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 215c50fa81e7..8b0d69a199fa 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 diff --git a/Source/Scene/OpenStreetMapImageryProvider.js b/Source/Scene/OpenStreetMapImageryProvider.js index 8e1857e29867..052ccb511a02 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 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 8811f5665124..0a489f9a42f2 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, @@ -38,6 +40,8 @@ define([ "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 31252edb92b2..07dc3b8a1180 100644 --- a/Source/Scene/UrlTemplateImageryProvider.js +++ b/Source/Scene/UrlTemplateImageryProvider.js @@ -53,8 +53,8 @@ define([ * @alias UrlTemplateImageryProvider * @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 {Promise|Object} [options] Object with the following properties: + * @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.options.pickFeaturesUrl
and attempt to interpret the features included in the response. If false,
@@ -147,48 +147,41 @@ define([
* 'width=256&height=256',
* rectangle : Cesium.Rectangle.fromDegrees(96.799393, -43.598214999057824, 153.63925700000001, -9.2159219997013)
* });
- *
+ *
* @see ArcGisMapServerImageryProvider
* @see BingMapsImageryProvider
* @see GoogleEarthImageryProvider
* @see createOpenStreetMapImageryProvider
* @see SingleTileImageryProvider
- * @see TileMapServiceImageryProvider
+ * @see createTileMapServiceImageryProvider
* @see WebMapServiceImageryProvider
* @see WebMapTileServiceImageryProvider
*/
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._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);
+ 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._readyPromise = undefined;
/**
* Gets or sets a value indicating whether feature picking is enabled. If true, {@link UrlTemplateImageryProvider#pickFeatures} will
@@ -199,18 +192,9 @@ define([
* @type {Boolean}
* @default true
*/
- this.enablePickFeatures = defaultValue(options.enablePickFeatures, true);
+ this.enablePickFeatures = true;
- var credit = options.credit;
- if (typeof credit === 'string') {
- credit = new Credit(credit);
- }
- this._credit = credit;
-
- this._urlParts = urlTemplateToParts(this._url, tags);
- this._pickFeaturesUrlParts = urlTemplateToParts(this._pickFeaturesUrl, pickFeaturesTags);
-
- this._readyPromise = when.resolve(true);
+ this.reinitialize(options);
}
defineProperties(UrlTemplateImageryProvider.prototype, {
@@ -293,6 +277,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;
}
},
@@ -307,6 +296,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;
}
},
@@ -321,6 +315,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;
}
},
@@ -335,6 +334,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;
}
},
@@ -349,6 +353,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;
}
},
@@ -363,6 +372,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;
}
},
@@ -379,6 +393,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;
}
},
@@ -405,7 +424,7 @@ define([
*/
ready : {
get : function() {
- return true;
+ return defined(this._urlParts);
}
},
@@ -431,6 +450,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;
}
},
@@ -440,7 +464,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
@@ -448,11 +473,70 @@ 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;
}
}
});
+ /**
+ * Reinitializes this instance. Reinitializing an instance already in use is supported, but it is not
+ * recommended because existing tiles provided by the imagery provider will not be updated.
+ *
+ * @param {Promise|Object} options Any of the options that may be passed to the {@see UrlTemplateImageryProvider} constructor.
+ */
+ UrlTemplateImageryProvider.prototype.reinitialize = function(options) {
+ var that = this;
+ that._readyPromise = when(options).then(function(properties) {
+ //>>includeStart('debug', pragmas.debug);
+ if (!defined(properties)) {
+ throw new DeveloperError('options is required.');
+ }
+ if (!defined(properties.url)) {
+ throw new DeveloperError('options.url is required.');
+ }
+ //>>includeEnd('debug');
+ that.enablePickFeatures = defaultValue(properties.enablePickFeatures, that.enablePickFeatures);
+ 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'];
+ }
+
+ 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;
+
+ that._urlParts = urlTemplateToParts(that._url, tags);
+ that._pickFeaturesUrlParts = urlTemplateToParts(that._pickFeaturesUrl, pickFeaturesTags);
+ return true;
+ });
+ };
+
/**
* Gets the credits to be displayed when a given tile is displayed.
*
@@ -464,6 +548,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;
};
@@ -480,6 +569,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);
};
@@ -499,6 +593,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 (!this.enablePickFeatures || !defined(this._pickFeaturesUrl) || this._getFeatureInfoFormats.length === 0) {
return undefined;
}
diff --git a/Source/Scene/WebMapServiceImageryProvider.js b/Source/Scene/WebMapServiceImageryProvider.js
index ea34b08181f8..5ab545c8ff90 100644
--- a/Source/Scene/WebMapServiceImageryProvider.js
+++ b/Source/Scene/WebMapServiceImageryProvider.js
@@ -74,7 +74,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 cd858d6bc6cf..1063a0833b26 100644
--- a/Source/Scene/WebMapTileServiceImageryProvider.js
+++ b/Source/Scene/WebMapTileServiceImageryProvider.js
@@ -93,7 +93,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 e14a50c41cca..79dea6d4ca41 100644
--- a/Source/Scene/createOpenStreetMapImageryProvider.js
+++ b/Source/Scene/createOpenStreetMapImageryProvider.js
@@ -42,7 +42,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..39a0361651ff
--- /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 = joinUrls(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 = joinUrls(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 179973c6cb92..6a5e882294a9 100644
--- a/Source/Widgets/BaseLayerPicker/BaseLayerPicker.js
+++ b/Source/Widgets/BaseLayerPicker/BaseLayerPicker.js
@@ -72,7 +72,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'
@@ -85,7 +85,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 8ed1c88f8253..2b5dbb235787 100644
--- a/Source/Widgets/BaseLayerPicker/createDefaultImageryProviderViewModels.js
+++ b/Source/Widgets/BaseLayerPicker/createDefaultImageryProviderViewModels.js
@@ -5,8 +5,8 @@ define([
'../../Scene/BingMapsImageryProvider',
'../../Scene/BingMapsStyle',
'../../Scene/createOpenStreetMapImageryProvider',
+ '../../Scene/createTileMapServiceImageryProvider',
'../../Scene/MapboxImageryProvider',
- '../../Scene/TileMapServiceImageryProvider',
'../BaseLayerPicker/ProviderViewModel'
], function(
buildModuleUrl,
@@ -14,8 +14,8 @@ define([
BingMapsImageryProvider,
BingMapsStyle,
createOpenStreetMapImageryProvider,
+ createTileMapServiceImageryProvider,
MapboxImageryProvider,
- TileMapServiceImageryProvider,
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')
});
}
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 463e62eca286..8c151896b9ed 100644
--- a/Specs/Scene/UrlTemplateImageryProviderSpec.js
+++ b/Specs/Scene/UrlTemplateImageryProviderSpec.js
@@ -597,4 +597,100 @@ defineSuite([
});
});
});
+
+ 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();
+ });
+
+ it('throws if getTileCredits called before provider is ready', function() {
+ var provider = new UrlTemplateImageryProvider(when.defer());
+
+ expect(function() {
+ return provider.getTileCredits();
+ }).toThrowDeveloperError();
+ });
+
+ it('throws if requestImage called before provider is ready', function() {
+ var provider = new UrlTemplateImageryProvider(when.defer());
+
+ expect(function() {
+ return provider.requestImage();
+ }).toThrowDeveloperError();
+ });
+
+ it('throws if pickFeatures called before provider is ready', function() {
+ var provider = new UrlTemplateImageryProvider(when.defer());
+
+ expect(function() {
+ return provider.pickFeatures();
+ }).toThrowDeveloperError();
+ });
});
diff --git a/Specs/Scene/createTileMapServiceImageryProviderSpec.js b/Specs/Scene/createTileMapServiceImageryProviderSpec.js
new file mode 100644
index 000000000000..3f6ceeb72646
--- /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 =
+ '