diff --git a/CHANGES.md b/CHANGES.md
index a0d082c9421b..4b4a8ae89b79 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -10,6 +10,7 @@ Change Log
##### Fixes :wrench:
* Interacting with the Cesium canvas will now blur the previously focused element. This prevents unintended modification of input elements when interacting with the globe.
+* `TileMapServiceImageryProvider` will now force `minimumLevel` to 0 if the `tilemapresource.xml` metadata request fails and the `rectangle` is too large for the given detail level [#8448](https://github.com/AnalyticalGraphicsInc/cesium/pull/8448)
### 1.67.0 - 2020-03-02
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index e5b2c6c6a879..655d6cb39c4c 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -248,3 +248,4 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute to Cesiu
* [Jan Wąsak](https://github.com/jhnwsk)
* [Julian Fell](https://github.com/jtfell)
* [Richard Becker](https://github.com/richard3d)
+* [Daniel Leone](https://github.com/danielleone)
diff --git a/Source/Scene/TileMapServiceImageryProvider.js b/Source/Scene/TileMapServiceImageryProvider.js
index 302c3ebb7474..b284d6ba3466 100644
--- a/Source/Scene/TileMapServiceImageryProvider.js
+++ b/Source/Scene/TileMapServiceImageryProvider.js
@@ -113,6 +113,38 @@ import UrlTemplateImageryProvider from './UrlTemplateImageryProvider.js';
this._xmlResource.fetchXML().then(this._metadataSuccess).otherwise(this._metadataFailure);
};
+ /**
+ * Mutates the properties of a given rectangle so it does not extend outside of the given tiling scheme's rectangle
+ */
+ function confineRectangleToTilingScheme(rectangle, tilingScheme) {
+ 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;
+ }
+ return rectangle;
+ }
+
+ function calculateSafeMinimumDetailLevel(tilingScheme, rectangle, minimumLevel) {
+ // 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) {
+ return 0;
+ }
+ return minimumLevel;
+ }
+
TileMapServiceImageryProvider.prototype._metadataSuccess = function(xml) {
var tileFormatRegex = /tileformat/i;
var tileSetRegex = /tileset/i;
@@ -221,28 +253,9 @@ import UrlTemplateImageryProvider from './UrlTemplateImageryProvider.js';
}
// 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;
- }
+ rectangle = confineRectangleToTilingScheme(rectangle, tilingScheme);
+ // clamp our minimum detail level to something that isn't going to request a ridiculous number of tiles
+ minimumLevel = calculateSafeMinimumDetailLevel(tilingScheme, rectangle, minimumLevel);
var templateResource = this._tmsResource.getDerivedResource({
url : '{z}/{x}/{reverseY}.' + fileExtension
@@ -267,10 +280,15 @@ import UrlTemplateImageryProvider from './UrlTemplateImageryProvider.js';
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);
+ // The rectangle must not be outside the bounds allowed by the tiling scheme.
+ rectangle = confineRectangleToTilingScheme(rectangle, tilingScheme);
+
+ // make sure we use a safe minimum detail level, so we don't request a ridiculous number of tiles
+ var minimumLevel = calculateSafeMinimumDetailLevel(tilingScheme, rectangle, options.maximumLevel);
var templateResource = this._tmsResource.getDerivedResource({
url : '{z}/{x}/{reverseY}.' + fileExtension
diff --git a/Specs/Scene/TileMapServiceImageryProviderSpec.js b/Specs/Scene/TileMapServiceImageryProviderSpec.js
index 7a5dfb708354..7278e386b131 100644
--- a/Specs/Scene/TileMapServiceImageryProviderSpec.js
+++ b/Specs/Scene/TileMapServiceImageryProviderSpec.js
@@ -20,6 +20,44 @@ import { when } from '../../Source/Cesium.js';
describe('Scene/TileMapServiceImageryProvider', function() {
+ var validSampleXmlString =
+ '' +
+ ' NE2_HR_LC_SR_W_DR_recolored.tif' +
+ ' ' +
+ ' EPSG:4326' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ '';
+
+ function patchRequestScheduler(xmlResponseString) {
+ Resource._Implementations.loadWithXhr = 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 xml = parser.parseFromString(xmlResponseString, 'text/xml');
+ deferred.resolve(xml);
+ }, 1);
+ };
+ }
+
+ function patchRequestSchedulerToRejectRequest() {
+ Resource._Implementations.loadWithXhr = 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() {
+ deferred.reject(new Error('whoops; rejecting xhr request'));
+ }, 1);
+ };
+ }
+
beforeEach(function() {
RequestScheduler.clearForSpecs();
});
@@ -37,6 +75,7 @@ describe('Scene/TileMapServiceImageryProvider', function() {
});
it('resolves readyPromise', function() {
+ patchRequestScheduler(validSampleXmlString);
var provider = new TileMapServiceImageryProvider({
url : 'made/up/tms/server/'
});
@@ -48,6 +87,7 @@ describe('Scene/TileMapServiceImageryProvider', function() {
});
it('resolves readyPromise when promise url is used', function() {
+ patchRequestScheduler(validSampleXmlString);
var provider = new TileMapServiceImageryProvider({
url : when.resolve('made/up/tms/server/')
});
@@ -59,6 +99,7 @@ describe('Scene/TileMapServiceImageryProvider', function() {
});
it('resolves readyPromise with Resource', function() {
+ patchRequestScheduler(validSampleXmlString);
var resource = new Resource({
url : 'made/up/tms/server/'
});
@@ -87,29 +128,20 @@ describe('Scene/TileMapServiceImageryProvider', function() {
});
it('rejects readyPromise on error', function() {
- Resource._Implementations.loadWithXhr = 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 =
- '' +
- ' ' +
- ' ' +
- ' EPSG:4326' +
- ' ' +
- ' ' +
- ' ' +
- ' ' +
- ' ' +
- ' ' +
- ' ' +
- '';
- var xml = parser.parseFromString(xmlString, 'text/xml');
- deferred.resolve(xml);
- }, 1);
- };
-
+ var xmlString =
+ '' +
+ ' ' +
+ ' ' +
+ ' EPSG:4326' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ '';
+ patchRequestScheduler(xmlString);
var provider = new TileMapServiceImageryProvider({
url : 'made/up/tms/server'
});
@@ -123,28 +155,19 @@ describe('Scene/TileMapServiceImageryProvider', function() {
});
it('rejects readyPromise on invalid xml', function() {
- Resource._Implementations.loadWithXhr = 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 =
- '' +
- ' ' +
- ' ' +
- ' EPSG:4326' +
- ' ' +
- ' ' +
- ' ' +
- ' ' +
- ' ' +
- ' ' +
- '';
- var xml = parser.parseFromString(xmlString, 'text/xml');
- deferred.resolve(xml);
- }, 1);
- };
-
+ var xmlString =
+ '' +
+ ' ' +
+ ' ' +
+ ' EPSG:4326' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ '';
+ patchRequestScheduler(xmlString);
var provider = new TileMapServiceImageryProvider({
url : 'made/up/tms/server'
});
@@ -166,6 +189,7 @@ describe('Scene/TileMapServiceImageryProvider', function() {
});
it('returns valid value for hasAlphaChannel', function() {
+ patchRequestScheduler(validSampleXmlString);
var provider = new TileMapServiceImageryProvider({
url : 'made/up/tms/server/'
});
@@ -178,6 +202,7 @@ describe('Scene/TileMapServiceImageryProvider', function() {
});
it('supports a slash at the end of the URL', function() {
+ patchRequestScheduler(validSampleXmlString);
var baseUrl = 'made/up/tms/server/';
var provider = new TileMapServiceImageryProvider({
url : baseUrl
@@ -201,6 +226,7 @@ describe('Scene/TileMapServiceImageryProvider', function() {
});
it('supports no slash at the endof the URL', function() {
+ patchRequestScheduler(validSampleXmlString);
var provider = new TileMapServiceImageryProvider({
url : 'http://made/up/tms/server'
});
@@ -223,6 +249,7 @@ describe('Scene/TileMapServiceImageryProvider', function() {
});
it('supports a query string at the end of the URL', function() {
+ patchRequestScheduler(validSampleXmlString);
var baseUrl = 'made/up/tms/server/';
var provider = new TileMapServiceImageryProvider({
url : baseUrl + '?a=some&b=query'
@@ -246,6 +273,7 @@ describe('Scene/TileMapServiceImageryProvider', function() {
});
it('requestImage returns a promise for an image and loads it for cross-origin use', function() {
+ patchRequestScheduler(validSampleXmlString);
var provider = new TileMapServiceImageryProvider({
url : 'made/up/tms/server/'
});
@@ -253,12 +281,10 @@ describe('Scene/TileMapServiceImageryProvider', function() {
return pollToPromise(function() {
return provider.ready;
}).then(function() {
- expect(provider.url).toEqual(getAbsoluteUri('made/up/tms/server/{z}/{x}/{reverseY}.png'));
+ // check some details about the tilemapresourcel.xml so we know we got parsed/configured properly
+ expect(provider.url).toEqual(getAbsoluteUri('made/up/tms/server/{z}/{x}/{reverseY}.jpg'));
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(Resource._Implementations, 'createImage').and.callFake(function(request, crossOrigin, deferred) {
// Just return any old image.
@@ -273,6 +299,7 @@ describe('Scene/TileMapServiceImageryProvider', function() {
});
it('when no credit is supplied, the provider has no logo', function() {
+ patchRequestScheduler(validSampleXmlString);
var provider = new TileMapServiceImageryProvider({
url : 'made/up/tms/server'
});
@@ -284,6 +311,7 @@ describe('Scene/TileMapServiceImageryProvider', function() {
});
it('turns the supplied credit into a logo', function() {
+ patchRequestScheduler(validSampleXmlString);
var providerWithCredit = new TileMapServiceImageryProvider({
url : 'made/up/gms/server',
credit : 'Thanks to our awesome made up source of this imagery!'
@@ -314,6 +342,8 @@ describe('Scene/TileMapServiceImageryProvider', function() {
});
it('rectangle passed to constructor does not affect tile numbering', function() {
+ patchRequestScheduler(validSampleXmlString);
+
var rectangle = new Rectangle(0.1, 0.2, 0.3, 0.4);
var provider = new TileMapServiceImageryProvider({
url : 'made/up/tms/server',
@@ -323,10 +353,12 @@ describe('Scene/TileMapServiceImageryProvider', function() {
return pollToPromise(function() {
return provider.ready;
}).then(function() {
+ // check some values coming from tilemapresource.xml
expect(provider.tileWidth).toEqual(256);
expect(provider.tileHeight).toEqual(256);
- expect(provider.maximumLevel).toBeUndefined();
- expect(provider.tilingScheme).toBeInstanceOf(WebMercatorTilingScheme);
+ expect(provider.maximumLevel).toEqual(2);
+ expect(provider.tilingScheme).toBeInstanceOf(GeographicTilingScheme);
+ // check our rectangle from the constructor is correctly used
expect(provider.rectangle.west).toEqualEpsilon(rectangle.west, CesiumMath.EPSILON14);
expect(provider.rectangle.east).toEqualEpsilon(rectangle.east, CesiumMath.EPSILON14);
expect(provider.rectangle.north).toEqualEpsilon(rectangle.north, CesiumMath.EPSILON14);
@@ -348,6 +380,7 @@ describe('Scene/TileMapServiceImageryProvider', function() {
});
it('uses maximumLevel passed to constructor', function() {
+ patchRequestScheduler(validSampleXmlString);
var provider = new TileMapServiceImageryProvider({
url : 'made/up/tms/server',
maximumLevel : 5
@@ -361,6 +394,7 @@ describe('Scene/TileMapServiceImageryProvider', function() {
});
it('raises error event when image cannot be loaded', function() {
+ patchRequestScheduler(validSampleXmlString);
var provider = new TileMapServiceImageryProvider({
url : 'made/up/tms/server'
});
@@ -410,24 +444,19 @@ describe('Scene/TileMapServiceImageryProvider', function() {
});
it('keeps the rectangle within the bounds allowed by the tiling scheme no matter what the tilemapresource.xml says.', function() {
- Resource._Implementations.loadWithXhr = function(url, responseType, method, data, headers, deferred, overrideMimeType) {
- var parser = new DOMParser();
- var xmlString =
- "" +
- ' dnb_land_ocean_ice.2012.54000x27000_geo.tif' +
- ' ' +
- ' EPSG:900913' +
- " " +
- " " +
- " " +
- " " +
- " " +
- ' ' +
- '';
- var xml = parser.parseFromString(xmlString, 'text/xml');
- deferred.resolve(xml);
- };
-
+ var xmlString =
+ "" +
+ ' dnb_land_ocean_ice.2012.54000x27000_geo.tif' +
+ ' ' +
+ ' EPSG:900913' +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ ' ' +
+ '';
+ patchRequestScheduler(xmlString);
var provider = new TileMapServiceImageryProvider({
url : 'made/up/tms/server'
});
@@ -447,24 +476,20 @@ describe('Scene/TileMapServiceImageryProvider', function() {
});
it('uses a minimum level if the tilemapresource.xml specifies one and it is reasonable', function() {
- Resource._Implementations.loadWithXhr = function(url, responseType, method, data, headers, deferred, overrideMimeType) {
- var parser = new DOMParser();
- var xmlString =
- "" +
- ' dnb_land_ocean_ice.2012.54000x27000_geo.tif' +
- ' ' +
- ' EPSG:900913' +
- " " +
- " " +
- " " +
- " " +
- " " +
- " " +
- ' ' +
- '';
- var xml = parser.parseFromString(xmlString, 'text/xml');
- deferred.resolve(xml);
- };
+ var xmlString =
+ "" +
+ ' dnb_land_ocean_ice.2012.54000x27000_geo.tif' +
+ ' ' +
+ ' EPSG:900913' +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ ' ' +
+ '';
+ patchRequestScheduler(xmlString);
var provider = new TileMapServiceImageryProvider({
url : 'made/up/tms/server'
@@ -479,24 +504,20 @@ describe('Scene/TileMapServiceImageryProvider', function() {
});
it('ignores the minimum level in the tilemapresource.xml if it is unreasonable', function() {
- Resource._Implementations.loadWithXhr = function(url, responseType, method, data, headers, deferred, overrideMimeType) {
- var parser = new DOMParser();
- var xmlString =
- "" +
- ' dnb_land_ocean_ice.2012.54000x27000_geo.tif' +
- ' ' +
- ' EPSG:900913' +
- " " +
- " " +
- " " +
- " " +
- " " +
- " " +
- ' ' +
- '';
- var xml = parser.parseFromString(xmlString, 'text/xml');
- deferred.resolve(xml);
- };
+ var xmlString =
+ "" +
+ ' dnb_land_ocean_ice.2012.54000x27000_geo.tif' +
+ ' ' +
+ ' EPSG:900913' +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ ' ' +
+ '';
+ patchRequestScheduler(xmlString);
var provider = new TileMapServiceImageryProvider({
url : 'made/up/tms/server'
@@ -511,24 +532,20 @@ describe('Scene/TileMapServiceImageryProvider', function() {
});
it('handles XML with casing differences', function() {
- Resource._Implementations.loadWithXhr = function(url, responseType, method, data, headers, deferred, overrideMimeType) {
- var parser = new DOMParser();
- var xmlString =
- "" +
- ' dnb_land_ocean_ice.2012.54000x27000_geo.tif' +
- ' ' +
- ' EPSG:900913' +
- " " +
- " " +
- " " +
- " " +
- " " +
- " " +
- ' ' +
- '';
- var xml = parser.parseFromString(xmlString, 'text/xml');
- deferred.resolve(xml);
- };
+ var xmlString =
+ "" +
+ ' dnb_land_ocean_ice.2012.54000x27000_geo.tif' +
+ ' ' +
+ ' EPSG:900913' +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ ' ' +
+ '';
+ patchRequestScheduler(xmlString);
var provider = new TileMapServiceImageryProvider({
url : 'made/up/tms/server'
@@ -543,24 +560,20 @@ describe('Scene/TileMapServiceImageryProvider', function() {
});
it('supports the global-mercator profile with a non-flipped, mercator bounding box', function() {
- Resource._Implementations.loadWithXhr = function(url, responseType, method, data, headers, deferred, overrideMimeType) {
- var parser = new DOMParser();
- var xmlString =
- '' +
- ' ' +
- ' ' +
- ' EPSG:900913' +
- ' ' +
- ' ' +
- ' ' +
- ' ' +
- ' ' +
- ' ' +
- ' ' +
- '';
- var xml = parser.parseFromString(xmlString, 'text/xml');
- deferred.resolve(xml);
- };
+ var xmlString =
+ '' +
+ ' ' +
+ ' ' +
+ ' EPSG:900913' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ '';
+ patchRequestScheduler(xmlString);
var provider = new TileMapServiceImageryProvider({
url : 'made/up/tms/server'
@@ -584,24 +597,20 @@ describe('Scene/TileMapServiceImageryProvider', function() {
});
it('supports the global-geodetic profile with a non-flipped, geographic bounding box', function() {
- Resource._Implementations.loadWithXhr = function(url, responseType, method, data, headers, deferred, overrideMimeType) {
- var parser = new DOMParser();
- var xmlString =
- '' +
- ' ' +
- ' ' +
- ' EPSG:4326' +
- ' ' +
- ' ' +
- ' ' +
- ' ' +
- ' ' +
- ' ' +
- ' ' +
- '';
- var xml = parser.parseFromString(xmlString, 'text/xml');
- deferred.resolve(xml);
- };
+ var xmlString =
+ '' +
+ ' ' +
+ ' ' +
+ ' EPSG:4326' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ '';
+ patchRequestScheduler(xmlString);
var provider = new TileMapServiceImageryProvider({
url : 'made/up/tms/server'
@@ -624,24 +633,20 @@ describe('Scene/TileMapServiceImageryProvider', function() {
});
it('supports the old mercator profile with a flipped, geographic bounding box', function() {
- Resource._Implementations.loadWithXhr = function(url, responseType, method, data, headers, deferred, overrideMimeType) {
- var parser = new DOMParser();
- var xmlString =
- '' +
- ' ' +
- ' ' +
- ' EPSG:900913' +
- ' ' +
- ' ' +
- ' ' +
- ' ' +
- ' ' +
- ' ' +
- ' ' +
- '';
- var xml = parser.parseFromString(xmlString, 'text/xml');
- deferred.resolve(xml);
- };
+ var xmlString =
+ '' +
+ ' ' +
+ ' ' +
+ ' EPSG:900913' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ '';
+ patchRequestScheduler(xmlString);
var provider = new TileMapServiceImageryProvider({
url : 'made/up/tms/server',
@@ -665,24 +670,20 @@ describe('Scene/TileMapServiceImageryProvider', function() {
});
it('supports the old geodetic profile with a flipped, geographic bounding box', function() {
- Resource._Implementations.loadWithXhr = function(url, responseType, method, data, headers, deferred, overrideMimeType) {
- var parser = new DOMParser();
- var xmlString =
- '' +
- ' ' +
- ' ' +
- ' EPSG:4326' +
- ' ' +
- ' ' +
- ' ' +
- ' ' +
- ' ' +
- ' ' +
- ' ' +
- '';
- var xml = parser.parseFromString(xmlString, 'text/xml');
- deferred.resolve(xml);
- };
+ var xmlString =
+ '' +
+ ' ' +
+ ' ' +
+ ' EPSG:4326' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ '';
+ patchRequestScheduler(xmlString);
var provider = new TileMapServiceImageryProvider({
url : 'made/up/tms/server',
@@ -706,28 +707,20 @@ describe('Scene/TileMapServiceImageryProvider', function() {
});
it('raises an error if tilemapresource.xml specifies an unsupported profile', function() {
- Resource._Implementations.loadWithXhr = 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 =
- '' +
- ' ' +
- ' ' +
- ' EPSG:4326' +
- ' ' +
- ' ' +
- ' ' +
- ' ' +
- ' ' +
- ' ' +
- ' ' +
- '';
- var xml = parser.parseFromString(xmlString, 'text/xml');
- deferred.resolve(xml);
- }, 1);
- };
+ var xmlString =
+ '' +
+ ' ' +
+ ' ' +
+ ' EPSG:4326' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ '';
+ patchRequestScheduler(xmlString);
var provider = new TileMapServiceImageryProvider({
url : 'made/up/tms/server'
@@ -745,4 +738,45 @@ describe('Scene/TileMapServiceImageryProvider', function() {
expect(errorRaised).toBe(true);
});
});
+
+ it('forces minimum detail level to zero if the tilemapresource.xml request fails and the constructor minimum level is too high', function () {
+ patchRequestSchedulerToRejectRequest();
+ var provider = new TileMapServiceImageryProvider({
+ url : 'made/up/tms/server/',
+ maximumLevel : 10
+ });
+
+ // we expect that our minimum detail level was forced to 0, even though we requested 10.
+ // this is because, our rectangle has been set to the entire world (the default), so a minimum
+ // detail level of 10 would hang the browser with too many tile requests.
+ // Forcing detail level to zero to is safe.
+ return provider.readyPromise.then(function() {
+ expect(provider.minimumLevel).toBe(0);
+ });
+ });
+
+ it('allows the constructor minimum detail level if the tilemapresource.xml request fails but the constructor rectangle is small enough', function () {
+ patchRequestSchedulerToRejectRequest();
+ var provider = new TileMapServiceImageryProvider({
+ url: 'made/up/tms/server/',
+ // a high minimum detail level
+ maximumLevel: 12,
+ // and a very small rectangle
+ rectangle: new Rectangle(
+ CesiumMath.toRadians(131.020889),
+ CesiumMath.toRadians(-25.354730),
+ CesiumMath.toRadians(131.054363),
+ CesiumMath.toRadians(-25.335803)
+ )
+ });
+
+ // we expect that our minimum detail level remains at 12, which is quite high, but that's okay
+ // because our rectangle is still small enough that it's not too many tiles.
+ return provider.readyPromise.then(function() {
+ expect(provider.minimumLevel).toBe(12);
+ // just make sure we're actually still using a small rectangle
+ expect(provider.rectangle.width).toBeLessThan(0.001);
+ expect(provider.rectangle.height).toBeLessThan(0.001);
+ });
+ });
});