Bing map API with Nokia Map and OpenStreetMap
This article explains how to use Bing map API with tiles provided by Nokia map and OpenStreetMap.
Article Metadata
Code Example
Article
Contents |
Introduction
Maps API can use TileSource to provide tiles images uri. It' s so possible to use it to give tiles images from Nokia map and OpenStreetMap
The media player is loading...
OpenStreetMap and Nokia Map use Mercator projection which can be used by Map API. Bing Maps Tile System article explain how this projection work.
Warning : To use Map API you need Bing Maps credential : How to: Use the Bing Maps Silverlight Control for Windows Phone
Mercator projection and TileSource
To use map with Mercator projection we need to set Mode attribute to MercatorMode
<phone:PhoneApplicationPage
...
xmlns:Maps="clr-namespace:Microsoft.Phone.Controls.Maps;assembly=Microsoft.Phone.Controls.Maps"
xmlns:MapsCore="clr-namespace:Microsoft.Phone.Controls.Maps.Core;assembly=Microsoft.Phone.Controls.Maps"
...>
...
<Maps:Map CredentialsProvider="bing map credentials here">
<Maps:Map.Mode>
<MapsCore:MercatorMode ></MapsCore:MercatorMode>
</Maps:Map.Mode>
<Maps:MapTileLayer x:Name="MapLayer">
</Maps:MapTileLayer>
</Maps:Map>
...
</phone:PhoneApplicationPage >
Maps:MapTileLayer will use to set our TileSource provider.
To create a new TileSource provider you only need to inherit TileSource and override the function
public virtual Uri GetUri( int x, int y, int zoomLevel)
- {x,y} is the tile coordinate
- zoomLevel is the tile zoom level.
OpenStreetMap tiles
OpenStreetMap tiles url are really simple :
http://OpenStreetMapUrl_base/zoom/x/y.png
- OpenStreetMapUrl_base depend which server you want to use.
- zoom, x and y are parameters given to GetUri function.
So you only need to check if zoom < zoom support by the server
public class OpenSreetMap : TileSource
{
OpenSreetMap()
{
//Uri base of an OpenSTreetMap server
UriFormat = "http://a.tile.openstreetmap.org/{0}/{1}/{2}.png"
}
public override Uri GetUri(int x, int y, int zoomLevel)
{
if (zoomLevel > 0 && zoomLevel <= 18)
{
var url = string.Format(UriFormat,
zoomLevel,
x,
y);
return new Uri(url);
}
//if zoom level is not supported, return null
return null;
}
}
A lot of OpenStreetMap server provide group of url to get a tile image. This can be used to accelerate tiles loading. Example use this specificity.
Nokia Map
In first, you need a AppId and a Token to use Nokia map. To create these credentials, go to http://api.developer.nokia.com/
Nokia map API is a rest full image provider. Base uri is
"http://m.nok.it/?app_id=" + app_id + "&token=" + token
TileSource must give uri for image of size 256x256. To fixe size you must add h and w properties
"http://m.nok.it/?app_id=" + app_id + "&token=" + token "&w=256&h=256"
zoomlevel parameter correspond to z properties of nokia map api. Cool it's really simple!!
Unfortunately no. Nokia maps doesn't use {x,y} tile coordinate. To resolve it, you must use ctrl property : the center point of the map image in {latitude, longitude}. To convert {X,Y} to a {latitude, longitude} center point,Bing Maps Tile System article give the function PixelXYToLatLong. This function convert pixel position to {latitude, longitude}. A tile have a size of 256x256, so coordinate of the first pixel of a tile is {256*X, 256*Y}. Like we need tile cente we will convert tile pixel center to {latitude, longitude}
public override Uri GetUri(int x, int y, int zoomLevel)
{
if (zoomLevel > 0 && zoomLevel<=20)
{
double latitude = 0;
double longitude = 0;
//tile pixel center to {latitude, longitude}
PixelXYToLatLong(256 * x+128, 256 * y +128, zoomLevel, out latitude, out longitude );
...
return new Uri(url);
}
return null;
}
We can now generate Nokia Map tile uri !!!!
public class Nokia : TileSource
{
static string app_id = "your app id";
static string token = "your token";
public Nokia()
{
//base uri
UriFormat = "http://m.nok.it/?app_id="+app_id+"&token="+token+"&h=256&w=256"
+"&ctr={0},{1}&z={2}";
}
//compute Map size from zoomlevel
public static uint MapSize(int zoomlevel)
{
return (uint)256 << zoomlevel;
}
private static double Clip(double n, double minValue, double maxValue)
{
return Math.Min(Math.Max(n, minValue), maxValue);
}
//convert Pixel map position to latitude/longiture
public void PixelXYToLatLong(int pixelX, int pixelY, int levelOfDetail, out double latitude, out double longitude)
{
double mapSize = MapSize(levelOfDetail);
double x = (Clip(pixelX, 0, mapSize - 1) / mapSize) - 0.5;
double y = 0.5 - (Clip(pixelY, 0, mapSize - 1) / mapSize);
latitude = 90 - 360 * Math.Atan(Math.Exp(-y * 2 * Math.PI)) / Math.PI;
longitude = 360 * x;
}
public override Uri GetUri(int x, int y, int zoomLevel)
{
if (zoomLevel > 0 && zoomLevel<=20)
{
double latitude = 0;
double longitude = 0;
PixelXYToLatLong(256 * x+128, 256 * y +128, zoomLevel, out a, out b);
var url = string.Format(UriFormat,
latitude.ToString("#.0000##", CultureInfo.InvariantCulture), //Use English number format
longitude.ToString("#.0000##", CultureInfo.InvariantCulture), //Use English number format
zoomLevel
);
return new Uri(url);
}
return null;
}
}
To improve this tile provider Nokia Map Api have two other interesting properties :
- ml : tile language
- t : tile type.
Example use these properties
Build Example
- To build example, you need http://silverlight.codeplex.com/.
- To use Nokia Map Api, you need credential and edit MapSource/Nokia.cs : Nokia Map Api
- To remove warning of Bing api, you need bing map credential and edit MainPage.xaml : How to: Use the Bing Maps Silverlight Control for Windows Phone

