summaryrefslogtreecommitdiff
path: root/misc/openlayers/lib/OpenLayers/Layer/Bing.js
diff options
context:
space:
mode:
Diffstat (limited to 'misc/openlayers/lib/OpenLayers/Layer/Bing.js')
-rw-r--r--misc/openlayers/lib/OpenLayers/Layer/Bing.js333
1 files changed, 333 insertions, 0 deletions
diff --git a/misc/openlayers/lib/OpenLayers/Layer/Bing.js b/misc/openlayers/lib/OpenLayers/Layer/Bing.js
new file mode 100644
index 0000000..0615285
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Layer/Bing.js
@@ -0,0 +1,333 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Layer/XYZ.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.Bing
+ * Bing layer using direct tile access as provided by Bing Maps REST Services.
+ * See http://msdn.microsoft.com/en-us/library/ff701713.aspx for more
+ * information. Note: Terms of Service compliant use requires the map to be
+ * configured with an <OpenLayers.Control.Attribution> control and the
+ * attribution placed on or near the map.
+ *
+ * Inherits from:
+ * - <OpenLayers.Layer.XYZ>
+ */
+OpenLayers.Layer.Bing = OpenLayers.Class(OpenLayers.Layer.XYZ, {
+
+ /**
+ * Property: key
+ * {String} API key for Bing maps, get your own key
+ * at http://bingmapsportal.com/ .
+ */
+ key: null,
+
+ /**
+ * Property: serverResolutions
+ * {Array} the resolutions provided by the Bing servers.
+ */
+ serverResolutions: [
+ 156543.03390625, 78271.516953125, 39135.7584765625,
+ 19567.87923828125, 9783.939619140625, 4891.9698095703125,
+ 2445.9849047851562, 1222.9924523925781, 611.4962261962891,
+ 305.74811309814453, 152.87405654907226, 76.43702827453613,
+ 38.218514137268066, 19.109257068634033, 9.554628534317017,
+ 4.777314267158508, 2.388657133579254, 1.194328566789627,
+ 0.5971642833948135, 0.29858214169740677, 0.14929107084870338,
+ 0.07464553542435169
+ ],
+
+ /**
+ * Property: attributionTemplate
+ * {String}
+ */
+ attributionTemplate: '<span class="olBingAttribution ${type}">' +
+ '<div><a target="_blank" href="http://www.bing.com/maps/">' +
+ '<img src="${logo}" /></a></div>${copyrights}' +
+ '<a style="white-space: nowrap" target="_blank" '+
+ 'href="http://www.microsoft.com/maps/product/terms.html">' +
+ 'Terms of Use</a></span>',
+
+ /**
+ * Property: metadata
+ * {Object} Metadata for this layer, as returned by the callback script
+ */
+ metadata: null,
+
+ /**
+ * Property: protocolRegex
+ * {RegExp} Regular expression to match and replace http: in bing urls
+ */
+ protocolRegex: /^http:/i,
+
+ /**
+ * APIProperty: type
+ * {String} The layer identifier. Any non-birdseye imageryType
+ * from http://msdn.microsoft.com/en-us/library/ff701716.aspx can be
+ * used. Default is "Road".
+ */
+ type: "Road",
+
+ /**
+ * APIProperty: culture
+ * {String} The culture identifier. See http://msdn.microsoft.com/en-us/library/ff701709.aspx
+ * for the definition and the possible values. Default is "en-US".
+ */
+ culture: "en-US",
+
+ /**
+ * APIProperty: metadataParams
+ * {Object} Optional url parameters for the Get Imagery Metadata request
+ * as described here: http://msdn.microsoft.com/en-us/library/ff701716.aspx
+ */
+ metadataParams: null,
+
+ /** APIProperty: tileOptions
+ * {Object} optional configuration options for <OpenLayers.Tile> instances
+ * created by this Layer. Default is
+ *
+ * (code)
+ * {crossOriginKeyword: 'anonymous'}
+ * (end)
+ */
+ tileOptions: null,
+
+ /** APIProperty: protocol
+ * {String} Protocol to use to fetch Imagery Metadata, tiles and bing logo
+ * Can be 'http:' 'https:' or ''
+ *
+ * Warning: tiles may not be available under both HTTP and HTTPS protocols.
+ * Microsoft approved use of both HTTP and HTTPS urls for tiles. However
+ * this is undocumented and the Imagery Metadata API always returns HTTP
+ * urls.
+ *
+ * Default is '', unless when executed from a file:/// uri, in which case
+ * it is 'http:'.
+ */
+ protocol: ~window.location.href.indexOf('http') ? '' : 'http:',
+
+ /**
+ * Constructor: OpenLayers.Layer.Bing
+ * Create a new Bing layer.
+ *
+ * Example:
+ * (code)
+ * var road = new OpenLayers.Layer.Bing({
+ * name: "My Bing Aerial Layer",
+ * type: "Aerial",
+ * key: "my-api-key-here",
+ * });
+ * (end)
+ *
+ * Parameters:
+ * options - {Object} Configuration properties for the layer.
+ *
+ * Required configuration properties:
+ * key - {String} Bing Maps API key for your application. Get one at
+ * http://bingmapsportal.com/.
+ * type - {String} The layer identifier. Any non-birdseye imageryType
+ * from http://msdn.microsoft.com/en-us/library/ff701716.aspx can be
+ * used.
+ *
+ * Any other documented layer properties can be provided in the config object.
+ */
+ initialize: function(options) {
+ options = OpenLayers.Util.applyDefaults({
+ sphericalMercator: true
+ }, options);
+ var name = options.name || "Bing " + (options.type || this.type);
+
+ var newArgs = [name, null, options];
+ OpenLayers.Layer.XYZ.prototype.initialize.apply(this, newArgs);
+ this.tileOptions = OpenLayers.Util.extend({
+ crossOriginKeyword: 'anonymous'
+ }, this.options.tileOptions);
+ this.loadMetadata();
+ },
+
+ /**
+ * Method: loadMetadata
+ */
+ loadMetadata: function() {
+ this._callbackId = "_callback_" + this.id.replace(/\./g, "_");
+ // link the processMetadata method to the global scope and bind it
+ // to this instance
+ window[this._callbackId] = OpenLayers.Function.bind(
+ OpenLayers.Layer.Bing.processMetadata, this
+ );
+ var params = OpenLayers.Util.applyDefaults({
+ key: this.key,
+ jsonp: this._callbackId,
+ include: "ImageryProviders"
+ }, this.metadataParams);
+ var url = this.protocol + "//dev.virtualearth.net/REST/v1/Imagery/Metadata/" +
+ this.type + "?" + OpenLayers.Util.getParameterString(params);
+ var script = document.createElement("script");
+ script.type = "text/javascript";
+ script.src = url;
+ script.id = this._callbackId;
+ document.getElementsByTagName("head")[0].appendChild(script);
+ },
+
+ /**
+ * Method: initLayer
+ *
+ * Sets layer properties according to the metadata provided by the API
+ */
+ initLayer: function() {
+ var res = this.metadata.resourceSets[0].resources[0];
+ var url = res.imageUrl.replace("{quadkey}", "${quadkey}");
+ url = url.replace("{culture}", this.culture);
+ url = url.replace(this.protocolRegex, this.protocol);
+ this.url = [];
+ for (var i=0; i<res.imageUrlSubdomains.length; ++i) {
+ this.url.push(url.replace("{subdomain}", res.imageUrlSubdomains[i]));
+ }
+ this.addOptions({
+ maxResolution: Math.min(
+ this.serverResolutions[res.zoomMin],
+ this.maxResolution || Number.POSITIVE_INFINITY
+ ),
+ numZoomLevels: Math.min(
+ res.zoomMax + 1 - res.zoomMin, this.numZoomLevels
+ )
+ }, true);
+ if (!this.isBaseLayer) {
+ this.redraw();
+ }
+ this.updateAttribution();
+ },
+
+ /**
+ * Method: getURL
+ *
+ * Paramters:
+ * bounds - {<OpenLayers.Bounds>}
+ */
+ getURL: function(bounds) {
+ if (!this.url) {
+ return;
+ }
+ var xyz = this.getXYZ(bounds), x = xyz.x, y = xyz.y, z = xyz.z;
+ var quadDigits = [];
+ for (var i = z; i > 0; --i) {
+ var digit = '0';
+ var mask = 1 << (i - 1);
+ if ((x & mask) != 0) {
+ digit++;
+ }
+ if ((y & mask) != 0) {
+ digit++;
+ digit++;
+ }
+ quadDigits.push(digit);
+ }
+ var quadKey = quadDigits.join("");
+ var url = this.selectUrl('' + x + y + z, this.url);
+
+ return OpenLayers.String.format(url, {'quadkey': quadKey});
+ },
+
+ /**
+ * Method: updateAttribution
+ * Updates the attribution according to the requirements outlined in
+ * http://gis.638310.n2.nabble.com/Bing-imagery-td5789168.html
+ */
+ updateAttribution: function() {
+ var metadata = this.metadata;
+ if (!metadata.resourceSets || !this.map || !this.map.center) {
+ return;
+ }
+ var res = metadata.resourceSets[0].resources[0];
+ var extent = this.map.getExtent().transform(
+ this.map.getProjectionObject(),
+ new OpenLayers.Projection("EPSG:4326")
+ );
+ var providers = res.imageryProviders || [],
+ zoom = OpenLayers.Util.indexOf(this.serverResolutions,
+ this.getServerResolution()),
+ copyrights = "", provider, i, ii, j, jj, bbox, coverage;
+ for (i=0,ii=providers.length; i<ii; ++i) {
+ provider = providers[i];
+ for (j=0,jj=provider.coverageAreas.length; j<jj; ++j) {
+ coverage = provider.coverageAreas[j];
+ // axis order provided is Y,X
+ bbox = OpenLayers.Bounds.fromArray(coverage.bbox, true);
+ if (extent.intersectsBounds(bbox) &&
+ zoom <= coverage.zoomMax && zoom >= coverage.zoomMin) {
+ copyrights += provider.attribution + " ";
+ }
+ }
+ }
+ var logo = metadata.brandLogoUri.replace(this.protocolRegex, this.protocol);
+ this.attribution = OpenLayers.String.format(this.attributionTemplate, {
+ type: this.type.toLowerCase(),
+ logo: logo,
+ copyrights: copyrights
+ });
+ this.map && this.map.events.triggerEvent("changelayer", {
+ layer: this,
+ property: "attribution"
+ });
+ },
+
+ /**
+ * Method: setMap
+ */
+ setMap: function() {
+ OpenLayers.Layer.XYZ.prototype.setMap.apply(this, arguments);
+ this.map.events.register("moveend", this, this.updateAttribution);
+ },
+
+ /**
+ * APIMethod: clone
+ *
+ * Parameters:
+ * obj - {Object}
+ *
+ * Returns:
+ * {<OpenLayers.Layer.Bing>} An exact clone of this <OpenLayers.Layer.Bing>
+ */
+ clone: function(obj) {
+ if (obj == null) {
+ obj = new OpenLayers.Layer.Bing(this.options);
+ }
+ //get all additions from superclasses
+ obj = OpenLayers.Layer.XYZ.prototype.clone.apply(this, [obj]);
+ // copy/set any non-init, non-simple values here
+ return obj;
+ },
+
+ /**
+ * Method: destroy
+ */
+ destroy: function() {
+ this.map &&
+ this.map.events.unregister("moveend", this, this.updateAttribution);
+ OpenLayers.Layer.XYZ.prototype.destroy.apply(this, arguments);
+ },
+
+ CLASS_NAME: "OpenLayers.Layer.Bing"
+});
+
+/**
+ * Function: OpenLayers.Layer.Bing.processMetadata
+ * This function will be bound to an instance, linked to the global scope with
+ * an id, and called by the JSONP script returned by the API.
+ *
+ * Parameters:
+ * metadata - {Object} metadata as returned by the API
+ */
+OpenLayers.Layer.Bing.processMetadata = function(metadata) {
+ this.metadata = metadata;
+ this.initLayer();
+ var script = document.getElementById(this._callbackId);
+ script.parentNode.removeChild(script);
+ window[this._callbackId] = undefined; // cannot delete from window in IE
+ delete this._callbackId;
+};