Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use Bing Quadkey tiles instead of x/y/z tiles in leafletjs map

I try to create a map with leaflet.js where it is possible to switch between different tile layers. It works great with tileservers that serve the tiles with the standard x,y and z(oom) schema. However, Microsoft Bing uses its own quadkey schema. I found a JavaScript function to convert xyz to quad, but I don't know how to use it. Please see my example:

function toQuad(x, y, z) {
    var quadkey = '';
    for ( var i = z; i >= 0; --i) {
        var bitmask = 1 << i;
        var digit = 0;
        if ((x & bitmask) !== 0) {
            digit |= 1;}
        if ((y & bitmask) !== 0) {
            digit |= 2;}
        quadkey += digit;
    }
    return quadkey;
};
var openstreetmap = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',{attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'}),
arcgissat  = L.tileLayer('http://{s}.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {subdomains: ['server', 'services'], attribution: '&copy; <a href="http://www.arcgis.com/">ArcGIS esri</a>'})
//   bingsat  = L.tileLayer('http://t{s}.tiles.virtualearth.net/tiles/a'+toQuad({x},{y},{z})+'.jpeg?g=1398', {subdomains: [0,1,2,3,4,5], attribution: '&copy; <a href="http://bing.com/maps">Bing Maps</a>'}),
var map = L.map('map', {
    center: [48.85,2.33],
    zoom: 10,
    layers: [openstreetmap]
});
var baseLayers = {
    "OpenStreetMap": openstreetmap,
//      "Bing Sat": bingsat,
            "ArcGIS esri Sat": arcgissat
};
L.control.layers(baseLayers, null, {collapsed: false}).addTo(map);

Basically I just don't know how to call the JavaScript function inside of the variable declaration with the {x}, {y} and {z} values that leafletjs provides.

like image 223
user168080 Avatar asked Jun 17 '13 18:06

user168080


People also ask

What coordinate System is Bing Maps?

The latitude and longitude are assumed to be on the WGS 84 datum. Even though Bing Maps uses a spherical projection, it's important to convert all geographic coordinates into a common datum, and WGS 84 was chosen to be that datum.

What are XYZ tiles?

XYZ tile layers are layers comprised of multiple tiles that are situated on a server and are made available to the public. Unlike WMTS that follow the OGC standard, the XYZ tile layers are the de facto OpenstreetMap standard.

What is a Quadkey?

The name quadkey is short for quadtree key. Each of these keys encodes a square region in latitude and longitude space organized by detail levels. At the first level, the whole mappable surface of the Earth splits into four quadkeys. Think of it as a map zoom level that allows you to see the entire world.


2 Answers

You can create a simple "BingLayer" by extending the L.TileLayer class. Then you just have to override the getTileUrl method to use the new template you prefer (i.e. for bing maps). See the linked fiddle for an example:

http://jsfiddle.net/nkmbx/

var BingLayer = L.TileLayer.extend({
getTileUrl: function (tilePoint) {
    this._adjustTilePoint(tilePoint);
    return L.Util.template(this._url, {
        s: this._getSubdomain(tilePoint),
        q: this._quadKey(tilePoint.x, tilePoint.y, this._getZoomForUrl())
    });
},
_quadKey: function (x, y, z) {
    var quadKey = [];
    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++;
        }
        quadKey.push(digit);
    }
    return quadKey.join('');
}
});
like image 87
user2494854 Avatar answered Oct 06 '22 06:10

user2494854


For leaflet=>1 above answer of @user2494854 doesnt work. Here is updated version of his answer that worked for me:

var BingLayer = L.TileLayer.extend({
getTileUrl: function(coords) {
var quadkey = this.toQuadKey(coords.x, coords.y, coords.z)
var url = L.Util.template(this._url, {
  q: quadkey,
  s: this._getSubdomain(coords)
})
if (typeof this.options.style === 'string') {
  url += '&st=' + this.options.style
}
return url
},
toQuadKey: function(x, y, z) {
var index = ''
for (var i = z; i > 0; i--) {
  var b = 0
  var mask = 1 << (i - 1)
  if ((x & mask) !== 0) b++
  if ((y & mask) !== 0) b += 2
  index += b.toString()
 }
  return index
 }
})
like image 26
Dany Avatar answered Oct 06 '22 08:10

Dany