Skip to content

Commit f93dfe8

Browse files
authoredMay 8, 2019
Merge pull request #7810 from AnalyticalGraphicsInc/bingMapsDiscardPolicy
Use DiscardEmptyTileImagePolicy for all Bing styles.
2 parents a35f010 + 9966a08 commit f93dfe8

6 files changed

+58
-62
lines changed
 

‎CHANGES.md

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Change Log
44

55
##### Additions :tada:
66
* Added support for new `BingMapsStyle` values `ROAD_ON_DEMAND` and `AERIAL_WITH_LABELS_ON_DEMAND`. The older versions of these, `ROAD` and `AERIAL_WITH_LABELS`, have been deprecated by Bing. [#7808](https://github.com/AnalyticalGraphicsInc/cesium/pull/7808)
7+
* `BingMapsImageryProvider` now uses `DiscardEmptyTileImagePolicy` by default to detect missing tiles as zero-length responses instead of inspecting pixel values. [#7810](https://github.com/AnalyticalGraphicsInc/cesium/pull/7810)
78

89
### 1.57 - 2019-05-01
910

‎Source/Core/Resource.js

+8-6
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ define([
1010
'./defineProperties',
1111
'./DeveloperError',
1212
'./freezeObject',
13-
'./FeatureDetection',
1413
'./getAbsoluteUri',
1514
'./getBaseUri',
1615
'./getExtensionFromUri',
@@ -38,7 +37,6 @@ define([
3837
defineProperties,
3938
DeveloperError,
4039
freezeObject,
41-
FeatureDetection,
4240
getAbsoluteUri,
4341
getBaseUri,
4442
getExtensionFromUri,
@@ -929,9 +927,11 @@ define([
929927
if (!defined(image)) {
930928
return;
931929
}
932-
// This is because the blob object is needed for DiscardMissingTileImagePolicy
933-
// See https://github.com/AnalyticalGraphicsInc/cesium/issues/1353
930+
931+
// The blob object may be needed for use by a TileDiscardPolicy,
932+
// so attach it to the image.
934933
image.blob = generatedBlob;
934+
935935
if (useImageBitmap) {
936936
return image;
937937
}
@@ -944,8 +944,10 @@ define([
944944
window.URL.revokeObjectURL(generatedBlobResource.url);
945945
}
946946

947-
// If the blob load succeeded but the image decode failed, provide access to the blob on the error object because it may provide useful insight.
948-
// In particular, BingMapsImageryProvider uses this to detect the zero-length "image" that some map styles return when a real tile is not available.
947+
// If the blob load succeeded but the image decode failed, attach the blob
948+
// to the error object for use by a TileDiscardPolicy.
949+
// In particular, BingMapsImageryProvider uses this to detect the
950+
// zero-length response that is returned when a tile is not available.
949951
error.blob = generatedBlob;
950952

951953
return when.reject(error);

‎Source/Scene/BingMapsImageryProvider.js

+16-35
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
define([
22
'../Core/BingMapsApi',
33
'../Core/buildModuleUrl',
4-
'../Core/Cartesian2',
54
'../Core/Check',
65
'../Core/Credit',
76
'../Core/defaultValue',
@@ -17,13 +16,11 @@ define([
1716
'../Core/WebMercatorTilingScheme',
1817
'../ThirdParty/when',
1918
'./BingMapsStyle',
20-
'./DiscardMissingTileImagePolicy',
2119
'./DiscardEmptyTileImagePolicy',
2220
'./ImageryProvider'
2321
], function(
2422
BingMapsApi,
2523
buildModuleUrl,
26-
Cartesian2,
2724
Check,
2825
Credit,
2926
defaultValue,
@@ -39,7 +36,6 @@ define([
3936
WebMercatorTilingScheme,
4037
when,
4138
BingMapsStyle,
42-
DiscardMissingTileImagePolicy,
4339
DiscardEmptyTilePolicy,
4440
ImageryProvider) {
4541
'use strict';
@@ -63,16 +59,9 @@ define([
6359
* for information on the supported cultures.
6460
* @param {Ellipsoid} [options.ellipsoid] The ellipsoid. If not specified, the WGS84 ellipsoid is used.
6561
* @param {TileDiscardPolicy} [options.tileDiscardPolicy] The policy that determines if a tile
66-
* is invalid and should be discarded. The default value will depend on the map style. If
67-
* `BingMapsStyle.AERIAL_WITH_LABELS_ON_DEMAND` or `BingMapsStyle.ROADS_ON_DEMAND` is used, then a
68-
* {@link DiscardEmptyTileImagePolicy} will be used to handle the Bing Maps API sending no content instead of
69-
* a missing tile image, a behaviour specific to that imagery set. In all other cases, a default
70-
* {@link DiscardMissingTileImagePolicy} is used which requests tile 0,0 at the maximum tile level and checks
71-
* pixels (0,0), (120,140), (130,160), (200,50), and (200,200). If all of these pixels are transparent, the
72-
* discard check is disabled and no tiles are discarded. If any of them have a non-transparent color, any
73-
* tile that has the same values in these pixel locations is discarded. The end result of these defaults
74-
* should be correct tile discarding for a standard Bing Maps server. To ensure that no tiles are discarded,
75-
* construct and pass a {@link NeverTileDiscardPolicy} for this parameter.
62+
* is invalid and should be discarded. By default, a {@link DiscardEmptyTileImagePolicy}
63+
* will be used, with the expectation that the Bing Maps server will send a zero-length response for missing tiles.
64+
* To ensure that no tiles are discarded, construct and pass a {@link NeverTileDiscardPolicy} for this parameter.
7665
*
7766
* @see ArcGisMapServerImageryProvider
7867
* @see GoogleEarthEnterpriseMapsProvider
@@ -109,7 +98,12 @@ define([
10998
this._tileProtocol = options.tileProtocol;
11099
this._mapStyle = defaultValue(options.mapStyle, BingMapsStyle.AERIAL);
111100
this._culture = defaultValue(options.culture, '');
101+
112102
this._tileDiscardPolicy = options.tileDiscardPolicy;
103+
if (!defined(this._tileDiscardPolicy)) {
104+
this._tileDiscardPolicy = new DiscardEmptyTilePolicy();
105+
}
106+
113107
this._proxy = options.proxy;
114108
this._credit = new Credit('<a href="http://www.bing.com"><img src="' + BingMapsImageryProvider.logoUrl + '" title="Bing Imagery"/></a>');
115109

@@ -172,22 +166,6 @@ define([
172166

173167
that._imageUrlTemplate = that._imageUrlTemplate.replace(/^http:/, tileProtocol);
174168

175-
// Install the default tile discard policy if none has been supplied.
176-
if (!defined(that._tileDiscardPolicy)) {
177-
// Our default depends on which map style we're using.
178-
if (that._mapStyle === BingMapsStyle.AERIAL_WITH_LABELS_ON_DEMAND
179-
|| that._mapStyle === BingMapsStyle.ROAD_ON_DEMAND) {
180-
// this map style uses a different API, which returns a tile with no data instead of a placeholder image
181-
that._tileDiscardPolicy = new DiscardEmptyTilePolicy();
182-
} else {
183-
that._tileDiscardPolicy = new DiscardMissingTileImagePolicy({
184-
missingImageUrl : buildImageResource(that, 0, 0, that._maximumLevel).url,
185-
pixelsToCheck : [new Cartesian2(0, 0), new Cartesian2(120, 140), new Cartesian2(130, 160), new Cartesian2(200, 50), new Cartesian2(200, 200)],
186-
disableCheckIfAllPixelsAreTransparent : true
187-
});
188-
}
189-
}
190-
191169
var attributionList = that._attributionList = resource.imageryProviders;
192170
if (!attributionList) {
193171
attributionList = that._attributionList = [];
@@ -547,11 +525,9 @@ define([
547525

548526
if (defined(promise)) {
549527
return promise.otherwise(function(error) {
550-
551-
// One possible cause of an error here is that the image we tried to load was empty. This isn't actually
552-
// a problem. In some imagery sets (eg. `BingMapsStyle.AERIAL_WITH_LABELS_ON_DEMAND`), an empty image is
553-
// returned rather than a blank "This Image is Missing" placeholder image. In this case, we supress the
554-
// error.
528+
// One cause of an error here is that the image we tried to load was zero-length.
529+
// This isn't actually a problem, since it indicates that there is no tile.
530+
// So, in that case we return the EMPTY_IMAGE sentinel value for later discarding.
555531
if (defined(error.blob) && error.blob.size === 0) {
556532
return DiscardEmptyTilePolicy.EMPTY_IMAGE;
557533
}
@@ -680,6 +656,11 @@ define([
680656
quadkey: BingMapsImageryProvider.tileXYToQuadKey(x, y, level),
681657
subdomain: subdomains[subdomainIndex],
682658
culture: imageryProvider._culture
659+
},
660+
queryParameters: {
661+
// this parameter tells the Bing servers to send a zero-length response
662+
// instead of a placeholder image for missing tiles.
663+
n: 'z'
683664
}
684665
});
685666
}

‎Source/Scene/DiscardEmptyTileImagePolicy.js

+26-8
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
define([
2-
'../Core/defined',
3-
'../Core/defaultValue'
4-
], function(
2+
'../Core/defined',
3+
'../Core/defineProperties'
4+
], function(
55
defined,
6-
defaultValue) {
6+
defineProperties) {
77
'use strict';
88

99
/**
1010
* A policy for discarding tile images that contain no data (and so aren't actually images).
11+
* This policy discards {@link DiscardEmptyTileImagePolicy.EMPTY_IMAGE}, which is
12+
* expected to be used in place of any empty tile images by the image loading code.
1113
*
1214
* @alias DiscardEmptyTileImagePolicy
1315
* @constructor
@@ -35,10 +37,26 @@ define([
3537
return DiscardEmptyTileImagePolicy.EMPTY_IMAGE === image;
3638
};
3739

38-
/**
39-
* Default value for representing an empty image.
40-
*/
41-
DiscardEmptyTileImagePolicy.EMPTY_IMAGE = {};
40+
var emptyImage;
41+
42+
defineProperties(DiscardEmptyTileImagePolicy, {
43+
/**
44+
* Default value for representing an empty image.
45+
* @type {Image}
46+
* @readonly
47+
* @memberof DiscardEmptyTileImagePolicy
48+
*/
49+
EMPTY_IMAGE: {
50+
get: function() {
51+
if (!defined(emptyImage)) {
52+
emptyImage = new Image();
53+
// load a blank data URI with a 1x1 transparent pixel.
54+
emptyImage.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=';
55+
}
56+
return emptyImage;
57+
}
58+
}
59+
});
4260

4361
return DiscardEmptyTileImagePolicy;
4462
});

‎Source/Scene/DiscardMissingTileImagePolicy.js

+2-4
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,13 @@ define([
33
'../Core/defined',
44
'../Core/DeveloperError',
55
'../Core/getImagePixels',
6-
'../Core/Resource',
7-
'../ThirdParty/when'
6+
'../Core/Resource'
87
], function(
98
defaultValue,
109
defined,
1110
DeveloperError,
1211
getImagePixels,
13-
Resource,
14-
when) {
12+
Resource) {
1513
'use strict';
1614

1715
/**

‎Specs/Scene/BingMapsImageryProviderSpec.js

+5-9
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,37 @@
11
defineSuite([
22
'Scene/BingMapsImageryProvider',
33
'Core/appendForwardSlash',
4-
'Core/DefaultProxy',
54
'Core/defined',
65
'Core/queryToObject',
76
'Core/RequestScheduler',
87
'Core/Resource',
98
'Core/WebMercatorTilingScheme',
109
'Scene/BingMapsStyle',
11-
'Scene/DiscardMissingTileImagePolicy',
10+
'Scene/DiscardEmptyTileImagePolicy',
1211
'Scene/Imagery',
1312
'Scene/ImageryLayer',
1413
'Scene/ImageryProvider',
1514
'Scene/ImageryState',
1615
'Specs/pollToPromise',
1716
'ThirdParty/Uri',
18-
'ThirdParty/when',
19-
'Scene/DiscardEmptyTileImagePolicy'
17+
'ThirdParty/when'
2018
], function(
2119
BingMapsImageryProvider,
2220
appendForwardSlash,
23-
DefaultProxy,
2421
defined,
2522
queryToObject,
2623
RequestScheduler,
2724
Resource,
2825
WebMercatorTilingScheme,
2926
BingMapsStyle,
30-
DiscardMissingTileImagePolicy,
27+
DiscardEmptyTileImagePolicy,
3128
Imagery,
3229
ImageryLayer,
3330
ImageryProvider,
3431
ImageryState,
3532
pollToPromise,
3633
Uri,
37-
when,
38-
DiscardEmptyTileImagePolicy) {
34+
when) {
3935
'use strict';
4036

4137
var supportsImageBitmapOptions;
@@ -366,7 +362,7 @@ defineSuite([
366362
expect(provider.tileHeight).toEqual(256);
367363
expect(provider.maximumLevel).toEqual(20);
368364
expect(provider.tilingScheme).toBeInstanceOf(WebMercatorTilingScheme);
369-
expect(provider.tileDiscardPolicy).toBeInstanceOf(DiscardMissingTileImagePolicy);
365+
expect(provider.tileDiscardPolicy).toBeInstanceOf(DiscardEmptyTileImagePolicy);
370366
expect(provider.rectangle).toEqual(new WebMercatorTilingScheme().rectangle);
371367
expect(provider.credit).toBeInstanceOf(Object);
372368

0 commit comments

Comments
 (0)
Please sign in to comment.