RadMap for Silverlight – How To Consume Tiles from Local Server

by XAML Team | Comments 4

Currently RadMap supports three built-in map providers: Bing Maps, Open Street Maps and Empty provider. The empty provider does not show any map tiles. It just provides spatial reference (projection) for other operations (i.e. KML or ESRI shape files).
The Bing Maps and Open Street Map providers read their tile images from internet. Of course a browser can use these images from its cache, but the Bing Maps provider requires internet connection because it uses a WCF service to get URLs of the tile images.
It is a common scenario that the map tiles would be fetched offline from a corporate server instead of internet.
This blog post will demonstrate how to create your own tile server which fetches the tiles and runs on localhost.

It is quite simple to create a tile server on localhost when you have images which can be identified by the zoom level and (x,y) position of the tile.

All that you need to do is put your tiles(the downloaded images) in a separate directory in the C:\inetpub\wwwroot folder for example. So if you have the OpenStreet map tiles organized in a way similar to the structure on the OpenStreet servers (zoom\x_pos\y_pos.png) then you can create tile server on localhost in a couple of steps:

1. Create new folder like "os_images" in the "C:\inetpub\wwwroot" folder.
2. Copy the whole structure of the OpenStreet images to this new folder.
Here are some details about how to achieve this:

First you need to download and save locally the map images(tiles) that you need to show. For example, if you are using the Openstreet map provider there is an application called Easy OpenstreetMap Downloader that can be used to do this automatically for you. You can find instructions here.

Now you can create new map tile source and map provider which will access images from this folder:

  1. /// <summary>
  2.     /// Tile source which read map tiles from the file system.
  3.     /// </summary>
  4.     public class LocalhostTileSource : TiledMapSource
  5.     {
  6.         private string tileUriFormat;
  7.  
  8.         /// <summary>
  9.         /// Initializes a new instance of the FileSystemTileSource class.
  10.         /// </summary>
  11.         /// <param name="tileUriFormat">Format string to access tiles on the localhost.</param>
  12.         public LocalhostTileSource(string tileUriFormat)
  13.             : base(1, 20, 256, 256)
  14.         {
  15.             this.tileUriFormat = tileUriFormat;
  16.         }
  17.  
  18.         /// <summary>
  19.         /// Initialize provider.
  20.         /// </summary>
  21.         public override void Initialize()
  22.         {
  23.             // Raise provider intialized event.
  24.             this.RaiseIntializeCompleted();
  25.         }
  26.  
  27.         /// <summary>
  28.         /// Gets the image URI.
  29.         /// </summary>
  30.         /// <param name="tileLevel">Tile level.</param>
  31.         /// <param name="tilePositionX">Tile X.</param>
  32.         /// <param name="tilePositionY">Tile Y.</param>
  33.         /// <returns>URI of image.</returns>
  34.         protected override Uri GetTile(int tileLevel, int tilePositionX, int tilePositionY)
  35.         {
  36.             int zoomLevel = ConvertTileToZoomLevel(tileLevel);
  37.  
  38.             string url = this.tileUriFormat.Replace("{zoom}", zoomLevel.ToString(CultureInfo.InvariantCulture));
  39.             url = url.Replace("{x}", tilePositionX.ToString(CultureInfo.InvariantCulture));
  40.             url = url.Replace("{y}", tilePositionY.ToString(CultureInfo.InvariantCulture));
  41.             return new Uri(url);
  42.         }
  43.     }
  44.  
  45.     /// <summary>
  46.     /// Map provider which read map tiles from the file system.
  47.     /// </summary>
  48.     public class LocalhostProvider : TiledProvider
  49.     {
  50.         /// <summary>
  51.         /// Initializes a new instance of the LocalhostProvider class.
  52.         /// </summary>
  53.         /// <param name="tileUriFormat">Format string to access tiles on the localhost.</param>
  54.         public LocalhostProvider(string tileUriFormat)
  55.             : base()
  56.         {
  57.             LocalhostTileSource source = new LocalhostTileSource(tileUriFormat);
  58.             this.MapSources.Add(source.UniqueId, source);
  59.         }
  60.  
  61.         /// <summary>
  62.         /// Returns the SpatialReference for the map provider.
  63.         /// </summary>
  64.         public override ISpatialReference SpatialReference
  65.         {
  66.             get
  67.             {
  68.                 return new MercatorProjection();
  69.             }
  70.         }
  71.     }

Here is how to use the new map provider in your application:

  1.    <UserControl x:Class="LocalhostMapProvider.MainPage"
  2.              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3.              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4.              xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
  5.              xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  6.              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  7.              mc:Ignorable="d"
  8.              d:DesignHeight="300" d:DesignWidth="400">
  9.    
  10.     <Grid x:Name="LayoutRoot" Background="White">
  11.         <telerik:RadMap x:Name="radMap"
  12.                         Center="48.95,2.3"
  13.                         ZoomLevel="13">
  14.         </telerik:RadMap>
  15.     </Grid>
  16. </UserControl>
  17. using System;
  18. using System.Collections.Generic;
  19. using System.Windows;
  20. using System.Windows.Controls;
  21.    
  22. namespace LocalhostMapProvider
  23. {
  24.     public partial class MainPage : UserControl
  25.     {
  26.         public MainPage()
  27.         {
  28.             InitializeComponent();
  29.    
  30.             this.radMap.Provider = new LocalhostProvider("http://localhost/os_images/{zoom}/{x}/{y}.png");
  31.         }
  32.     }
  33. }

The ConvertTileToZoomLevel method is inherited from TiledMapSource class so you don't need to bother about its implementation.

Note: Download and usage of the Bing map tiles besides the Bing services is illegal. It is prohibited by the Microsoft Bing license agreement and we discourage you from using it as sample offline provider. If you have some questions do not hesitate to drop us a line here or in the Forum threads.

Happy coding with our controls!

About the author

Evgenia Milcheva

is a Front-End Developer in Telerik with more than two years of experience supporting and creating Silverlight & WPF applications with Telerik’s DataVisualization controls..

4 Comments

Arash Khodadadi
This is a useful solution for providing offline map server. But, if I stored my tiles in a database how can I achieve this goal? I don't want to read from a file from my server, I want to load them from a database.
Jason
Handle GetCachedTile instead of GetTile. The former returns a stream instead of a file URI.
Chaitanya Duse
Hi,
I am trying to load RadMap using local tile server according to the above example. But I am not able to get tiles for say India in the
zoom/x/y.png format.
Could anyone of you tell me where I would get filess in the proper format
I used a tool call gmapcatcher which downloads the tiles from OSM according to zoom levels. But the X and Y part is not clear.
Guidance will be appreciated.
Chaitanya Duse
Hi,
I am trying to load RadMap using local tile server according to the above example. But I am not able to get tiles for say India in the
zoom/x/y.png format.
Could anyone of you tell me where I would get filess in the proper format
I used a tool call gmapcatcher which downloads the tiles from OSM according to zoom levels. But the X and Y part is not clear.
Guidance will be appreciated.

Comments

  1.    
      
      
       
  2. (optional, emails won't be shown on public pages)
  3. (optional)
Read more articles by XAML Team - or - read latest articles in Developer Tools