Displaying Open Street Map and ESRI tiles on Bing Maps AJAX v7

In a previous post, I explained how to replace the base tile layer in the Bing Maps Silverlight control with an ESRI tile layer. In this post, I’ll show how to do the same but using the Bing Maps AJAX v7 control. You can use this technique to use the Bing Maps AJAX control, but replace the Bing imagery with OSM tiles or the ESRI tile layers used in the previous Silverlight post, as well as many other tile sources.

The first step is to specify not to load the default Bing Maps tile layer. Do this by specifying the mercator MapTypeId in the options passed to the constructor when you first initialise the map:

mapTypeId: Microsoft.Maps.MapTypeId.mercator

The next step is to create a new TileSource. The uriConstructor of the TileSource must return the correct URI for a requested tile. If your tile provider names its tiles according to the default Bing Maps quadkey numbering system, then the uriConstructor can be a simple string using the {quadkey} placeholder. This will be replaced with the appropriate quadkey when the tile is requested:

var tileSource = new Microsoft.Maps.TileSource(
 {  uriConstructor: 'http://www.microsoft.com/maps/isdk/ajax/layers/lidar/{quadkey}.png' }
);

However, for OSM tiles, or any other tile providers that not follow the basic quadkey numbering system, we instead need a function to construct the appropriate URI for each tile. I’ll do this in a function called getTilePath, and I’ll specify this in the TileSource uriConstructor as follows:

var tileSource = new Microsoft.Maps.TileSource({ uriConstructor: getTilePath });

The getTilePath function will return a string with the appropriate URI for the requested tile. For OSM tiles, a typical tile looks like http://tile.openstreetmap.org/zoom/x/y.png. The function to create this tile is therefore:

function getTilePath(tile) {
 return "http://tile.openstreetmap.org/" + tile.levelOfDetail + "/" + tile.x + "/" + tile.y + ".png";
}

Put this all together and your code should look like this:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html  xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0"></script>
<script type="text/javascript">
 function GetMap() {
 // Create a basic map
 var map = new Microsoft.Maps.Map(document.getElementById("mapDiv"),
 { credentials: "YOURBINGMAPSKEYHERE",
 center: new Microsoft.Maps.Location(56, 2),
 zoom: 5,
 // Don't load the Bing base map tiles
 mapTypeId: Microsoft.Maps.MapTypeId.mercator
 });

// Create the tile source
 var tileSource = new Microsoft.Maps.TileSource({ uriConstructor: getTilePath });

// Construct the layer using the tile source
 var tilelayer = new Microsoft.Maps.TileLayer({ mercator: tileSource, opacity: 1 });

// Push the tile layer to the map
 map.entities.push(tilelayer);
 }

function getTilePath(tile) {
 // Construct the URI path for an OSM tile based on tile zoom/x/y
 return "http://tile.openstreetmap.org/" + tile.levelOfDetail + "/" + tile.x + "/" + tile.y + ".png";
 }
</script>
</head>
<body onload="GetMap();">
 <div id='mapDiv' style="position:relative; width:640px; height:480px;"></div>
</body>
</html>

And here’s what it looks like:

image

If you want to try some other tile providers, replace the URI constructed by the getTilePath() function with some of the following:

DeLorme World Basemap

function getTilePath(tile) {
 return "http://server.arcgisonline.com/ArcGIS/rest/services/Specialty/DeLorme_World_Base_Map/MapServer/tile/" + tile.levelOfDetail + "/" + tile.y + "/" + tile.x;
 }

image

ESRI World Imagery

function getTilePath(tile) {
return "http://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/" + tile.levelOfDetail + "/" + tile.y + "/" + tile.x;
}

image

About these ads
This entry was posted in Bing Maps, Open Street Maps, Spatial and tagged , , , , . Bookmark the permalink.

8 Responses to Displaying Open Street Map and ESRI tiles on Bing Maps AJAX v7

  1. Pingback: Using ESRI Base Map Tile Layers in Bing Maps | Alastair Aitchison

  2. Pedro Sousa says:

    Alastair, you rock :)

  3. Steve Kahler says:

    I’m reading your article entitled “Displaying Open Street Map and ESRI tiles on Bing Maps AJAX v7″ and wondering where the “tile” variable is passed in from to the

    function getTilePath(tile) ?

    Also where is this documented in the Bing API ? What is tile.x and tile.y ?

    Thanks, Steve Kahler.

    • alastaira says:

      It’s not documented in the API – that’s why I’m writing about it here ;) I don’t just write out stuff from MSDN on this blog, y’know!
      If you open up veapicore.js you can look at the getUriConstructor method – it basically accepts a tile object, which has properties x and y to represent the row and column at which that tile should be placed on the map.

  4. sam says:

    Hi alastaira,
    do you know if possible to make the map control work in disconnected mode?
    We are servicing our own tiles using a lightweight web server hosted on the same machine (http://localhost/blabla); however it looks like the map control stop displaying tiles whenever the machine is disconnected from the internet. (we verified that the map control continue to request the tiles from the localhost, but they are not displayed for some reason.)

    Any help is really appreciated!
    -Sam

  5. sam says:

    Hi alastaira, and thank you for this great article.

    We are in the process of implementing something similar using the Bing Maps AJAX Control version 7, and I was wondering whether you know of any JS function to redraw the “Map” view, refresh a specific “TileLayer” or even refresh a specific Tile.

    This functionality is very useful for those cases where you need to manually update the a TileLayer in the current map view, knowing that the underlying source data of your tiles has changed.

    Any help is really appreciated.
    -Sam

  6. Alastaira, I stumbled upon your code while searching for an answer I am in need of. Reading the API for Bing AJAX V7 I cannot find a way to use dynamic overlays on the map. Just as ESRI services offer tiled map services, it also has the ability to have dynamically created layers that can have conditional queries passed in to allow one to manipulate the data.

    If you know of any sources I could look at, or have any knowledge of how I might solve this, I would be very grateful!

    Cheers

    • alastaira says:

      By “dynamic” overlays, you mean tile layers that are created from data at runtime (eg based on data retireved from a DB query, or similar)?
      Yes, you can do this – what you need to do is create a custom tile layer, but instead of pointing it at a directory or pre-rendered PNG/JPG tiles, you point it at a custom tile handler – an .ASHX or .PHP file, say. You pass parameters to the handler with the quadkey of the tile you want to create, and other settings to customise the tile and choose what features are rendered etc. The handler uses the quadkey to retrieve and render the features that lie within the bounds of this tile from the database and generates an image on the fly (using, say, the System.Drawing classes in .NET, or GDI in PHP), and returns the image to Bing Maps.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s