Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added support for Bing Maps' AerialWithLabelsOnDemand imagery set, as… #41

Merged
merged 5 commits into from
May 2, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 40 additions & 6 deletions Source/Scene/BingMapsImageryProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ define([
'../ThirdParty/when',
'./BingMapsStyle',
'./DiscardMissingTileImagePolicy',
'./DiscardEmptyTileImagePolicy',
'./ImageryProvider'
], function(
BingMapsApi,
Expand All @@ -39,6 +40,7 @@ define([
when,
BingMapsStyle,
DiscardMissingTileImagePolicy,
DiscardEmptyTilePolicy,
ImageryProvider) {
'use strict';

Expand Down Expand Up @@ -71,6 +73,18 @@ define([
* that no tiles are discarded, construct and pass a {@link NeverTileDiscardPolicy} for this
* parameter.
*
* @param {TileDiscardPolicy} [options.tileDiscardPolicy] The policy that determines if a tile
* is invalid and should be discarded. The default value will depend on the map style. If
* BingMapsStyle.AERIAL_WITH_LABELS_ON_DEMAND is used, then a {@link DiscardEmptyTileImagePolicy} will be
* used to handle the Bing Maps API sending no content instead of a missing tile image, a behaviour specific
* to that imagery set. In all over cases, a default {@link DiscardMissingTileImagePolicy} is used which
* requests tile 0,0 at the maximum tile level and checks pixels (0,0), (120,140), (130,160), (200,50), and
* (200,200). If all of these pixels are transparent, the discard check is disabled and no tiles are
* discarded. If any of them have a non-transparent color, any tile that has the same values in these pixel
* locations is discarded. The end result of these defaults should be correct tile discarding for a standard
* Bing Maps server. To ensure that no tiles are discarded, construct and pass a
* {@link NeverTileDiscardPolicy} for this parameter.
*
* @see ArcGisMapServerImageryProvider
* @see GoogleEarthEnterpriseMapsProvider
* @see createOpenStreetMapImageryProvider
Expand Down Expand Up @@ -171,11 +185,17 @@ define([

// Install the default tile discard policy if none has been supplied.
if (!defined(that._tileDiscardPolicy)) {
that._tileDiscardPolicy = new DiscardMissingTileImagePolicy({
missingImageUrl : buildImageResource(that, 0, 0, that._maximumLevel).url,
pixelsToCheck : [new Cartesian2(0, 0), new Cartesian2(120, 140), new Cartesian2(130, 160), new Cartesian2(200, 50), new Cartesian2(200, 200)],
disableCheckIfAllPixelsAreTransparent : true
});
// Our default depends on which map style we're using.
if (that._mapStyle === BingMapsStyle.AERIAL_WITH_LABELS_ON_DEMAND) {
// this map style uses a different API, which returns a tile with no data instead of a placeholder image
that._tileDiscardPolicy = new DiscardEmptyTilePolicy();
} else {
that._tileDiscardPolicy = new DiscardMissingTileImagePolicy({
missingImageUrl : buildImageResource(that, 0, 0, that._maximumLevel).url,
pixelsToCheck : [new Cartesian2(0, 0), new Cartesian2(120, 140), new Cartesian2(130, 160), new Cartesian2(200, 50), new Cartesian2(200, 200)],
disableCheckIfAllPixelsAreTransparent : true
});
}
}

var attributionList = that._attributionList = resource.imageryProviders;
Expand Down Expand Up @@ -533,7 +553,21 @@ define([
}
//>>includeEnd('debug');

return ImageryProvider.loadImage(this, buildImageResource(this, x, y, level, request));
var promise = ImageryProvider.loadImage(this, buildImageResource(this, x, y, level, request));

if(defined(promise)) {
return promise.then(() => promise, (error) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use promise.otherwise instead of two-parameter then.

// If there isn't any image, we get an InvalidStateError.
// The version of the Bing maps API that we hit if we're using `BingMapsStyle.AERIAL_WITH_LABELS_ON_DEMAND` does this
// instead of returning a "This image is missing" image.
// Since this isn't really an error, we want to supress the one that just got thrown.
if (error.name === 'InvalidStateError' && error.message === 'The source image could not be decoded.') {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test isn't great, because there are other reasons that image decoding could fail. I think the best solution is to change Resource.prototype.fetchImage to attach the generatedBlob to the error object in the otherwise block. Then you can check for it on the error and check if its size is zero.

return {};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Declare a module-scope missingImage field, intiailized to {}, and return that here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better yet, declare the field on DiscardEmptyTileImagePolicy. Then in the discard policy you can just check for a missingImage rather than looking at the blob at all.

}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're not handling the error, you need to re-throw it. Otherwise it acts like a successful result yielding undefined.

});
}

return undefined;
};

/**
Expand Down
10 changes: 10 additions & 0 deletions Source/Scene/BingMapsStyle.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,19 @@ define([
*
* @type {String}
* @constant
* @deprecated See https://github.com/AnalyticalGraphicsInc/cesium/issues/7128.
* Use `BingMapsStyle.AERIAL_WITH_LABELS_ON_DEMAND` instead
*/
AERIAL_WITH_LABELS : 'AerialWithLabels',

/**
* Aerial imagery with a road overlay.
*
* @type {String}
* @constant
*/
AERIAL_WITH_LABELS_ON_DEMAND : 'AerialWithLabelsOnDemand',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add the other new styles, too: https://docs.microsoft.com/en-us/bingmaps/rest-services/imagery/get-imagery-metadata
It doesn't make sense to add the BirdsEye or Streetside ones, but the others should be added.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a couple still missing (unless there's some reason I'm not aware of that they can't be used):
CanvasDark, CanvasLight, CanvasGray, and OrdnanceSurvey


/**
* Roads without additional imagery.
*
Expand Down
36 changes: 36 additions & 0 deletions Source/Scene/DiscardEmptyTileImagePolicy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
define([
'../Core/defined'
], function(
defined) {
/**
* A policy for discarding tile images that contain no data (and so aren't actually images).
*
* @alias DiscardEmptyTileImagePolicy
* @constructor
*
* @see DiscardMissingTileImagePolicy
*/
function DiscardEmptyTileImagePolicy(options) {
}

/**
* Determines if the discard policy is ready to process images.
* @returns {Boolean} True if the discard policy is ready to process images; otherwise, false.
*/
DiscardEmptyTileImagePolicy.prototype.isReady = function() {
return true;
};

/**
* Given a tile image, decide whether to discard that image.
*
* @param {Image} image An image to test.
* @returns {Boolean} True if the image should be discarded; otherwise, false.
*/
DiscardEmptyTileImagePolicy.prototype.shouldDiscardImage = function(image) {
// If the image blob is non-existent, or its size is zero, then discard it
return !defined(image.blob) || image.blob.size === 0;
};

return DiscardEmptyTileImagePolicy;
});