Can I use the telerik map contol, with one of the providers such as:
Bind, open source, google or any other you may know, while
the computer is not conected to the Internet?
I have a local server at the site which is conected to the web.
And maybe it can be used as the tiles provider, but I have no
Idea how to implement this.
Thank you,
Or.
16 Answers, 1 is accepted
It is possible to use the map control while offline. Here are some details about how to achieve this:
- First you need to download and save locally the 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.
- Create custom map provider to read the Open Street tiles from the file system.
Here is some example code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Telerik.Windows.Controls.Map;
namespace Telerik.RadMap.WPF
{
public class FileSystemProvider : MapProviderBase
{
private const int TILE_SIZE = 256;
private bool initialized;
private string tileLocation;
/// <
summary
>
/// Initializes a new instance of the FileSystemProvider class.
/// </
summary
>
/// <
param
name
=
"mode"
>Map mode.</
param
>
/// <
param
name
=
"labelVisible"
>Is labels visible.</
param
>
public FileSystemProvider(string tileLocation)
: base(MapMode.Road, true)
{
this.tileLocation = tileLocation;
}
/// <
summary
>
/// Initializes a new instance of the FileSystemProvider class.
/// </
summary
>
public FileSystemProvider()
: this(null)
{
}
/// <
summary
>
/// Gets or sets location of the map tiles.
/// </
summary
>
public string TileLocation
{
get
{
return this.tileLocation;
}
set
{
this.tileLocation = value;
}
}
/// <
summary
>
/// Gets the IsInitialized property.
/// Indicates that the provider is initialized.
/// </
summary
>
public override bool IsInitialized
{
get
{
return this.initialized;
}
}
/// <
summary
>
/// Gets value which indicates whether labels are supported by the map provider.
/// </
summary
>
public override bool IsLabelSupported
{
get
{
return false;
}
}
/// <
summary
>
/// Returns the SpatialReference for the map provider.
/// </
summary
>
public override ISpatialReference SpatialReference
{
get
{
return new MercatorProjection();
}
}
/// <
summary
>
/// Gets list of the supported map modes.
/// </
summary
>
/// <
returns
>List of the supported map modes.</
returns
>
public override IEnumerable<
MapMode
> SupportedModes
{
get
{
yield return MapMode.Road;
}
}
/// <
summary
>
/// Gets the image URI.
/// </
summary
>
/// <
param
name
=
"tileLevel"
>Tile level.</
param
>
/// <
param
name
=
"tilePositionX"
>Tile X.</
param
>
/// <
param
name
=
"tilePositionY"
>Tile Y.</
param
>
/// <
returns
>URI of image.</
returns
>
public override Uri GetTile(int tileLevel, int tilePositionX, int tilePositionY)
{
int zoomLevel = ConvertTileToZoomLevel(tileLevel);
string tileFileName = string.Format("os_{0}_{1}_{2}.png", tilePositionX, tilePositionY, zoomLevel);
tileFileName = Path.Combine(this.TileLocation, tileFileName);
if (File.Exists(tileFileName))
{
return new Uri(tileFileName);
}
else
{
return null;
}
}
/// <
summary
>
/// Initialize provider.
/// </
summary
>
public override void Initialize()
{
this.initialized = base.IsInitialized;
}
/// <
summary
>
/// Gets value which indicates whether given mode is supported by map provider.
/// </
summary
>
/// <
param
name
=
"mode"
>Map mode to check.</
param
>
/// <
returns
>true if given mode is supported. Otherwise - false.</
returns
>
public override bool IsModeSupported(MapMode mode)
{
return (mode == MapMode.Road);
}
/// <
summary
>
/// MapModeChanged handler.
/// </
summary
>
protected override void OnMapModeChanged(MapMode oldMode, MapMode newMode)
{
if (!this.IsSuspended)
{
this.Initialize();
}
}
}
}
Here is an example of using the file system map provider in XAML.
<
Window
x:Class
=
"Telerik.RadMap.WPF.MainWindow"
xmlns:telerik
=
"http://schemas.telerik.com/2008/xaml/presentation"
xmlns:app
=
"clr-namespace:Telerik.RadMap.WPF"
Title
=
"MainWindow"
Height
=
"350"
Width
=
"525"
>
<
Grid
>
<
telerik:RadMap
x:Name
=
"radMap"
Center
=
"48.5,2.25"
ZoomLevel
=
"13"
>
<
telerik:RadMap.Provider
>
<
app:FileSystemProvider
TileLocation
=
"D:\Andrey\Telerik\OpenStreet Images\paris_13_cycle"
/>
</
telerik:RadMap.Provider
>
</
telerik:RadMap
>
</
Grid
>
</
Window
>
Hope this will help.
All the best,
Ryan
the Telerik team
Is there a solution to this in Q1 2011 release? I tried this example earlier today with no luck.
Thanks Much,
~Boots
The architecture of the map providers has been changed since this post. With 2011 Q1 release it should look like the following:
/// <summary>
/// Tile source which read map tiles from the file system.
/// </summary>
public
class
FileSystemTileSource : TiledMapSource
{
private
string
tilePathFormat;
/// <summary>
/// Initializes a new instance of the FileSystemTileSource class.
/// </summary>
/// <param name="tilePathFormat">Format string to access tiles in file system.</param>
public
FileSystemTileSource(
string
tilePathFormat)
:
base
(1, 20, 256, 256)
{
this
.tilePathFormat = tilePathFormat;
}
/// <summary>
/// Initialize provider.
/// </summary>
public
override
void
Initialize()
{
// Raise provider intialized event.
this
.RaiseIntializeCompleted();
}
/// <summary>
/// Gets the image URI.
/// </summary>
/// <param name="tileLevel">Tile level.</param>
/// <param name="tilePositionX">Tile X.</param>
/// <param name="tilePositionY">Tile Y.</param>
/// <returns>URI of image.</returns>
protected
override
Uri GetTile(
int
tileLevel,
int
tilePositionX,
int
tilePositionY)
{
int
zoomLevel = ConvertTileToZoomLevel(tileLevel);
string
tileFileName =
this
.tilePathFormat.Replace(
"{zoom}"
, zoomLevel.ToString(CultureInfo.InvariantCulture));
tileFileName = tileFileName.Replace(
"{x}"
, tilePositionX.ToString(CultureInfo.InvariantCulture));
tileFileName = tileFileName.Replace(
"{y}"
, tilePositionY.ToString(CultureInfo.InvariantCulture));
if
(File.Exists(tileFileName))
{
return
new
Uri(tileFileName);
}
else
{
return
null
;
}
}
}
/// <summary>
/// Map provider which read map tiles from the file system.
/// </summary>
public
class
FileSystemProvider : TiledProvider
{
/// <summary>
/// Initializes a new instance of the MyMapProvider class.
/// </summary>
/// <param name="tilePathFormat">Format string to access tiles in file system.</param>
public
FileSystemProvider(
string
tilePathFormat)
:
base
()
{
FileSystemTileSource source =
new
FileSystemTileSource(tilePathFormat);
this
.MapSources.Add(source.UniqueId, source);
}
/// <summary>
/// Returns the SpatialReference for the map provider.
/// </summary>
public
override
ISpatialReference SpatialReference
{
get
{
return
new
MercatorProjection();
}
}
}
public
MainWindow()
{
InitializeComponent();
this
.radMap.Provider =
new
FileSystemProvider(
"Path to OpenStreet Images\\{zoom}\\{x}\\os_{x}_{y}_{zoom}.png"
);
}
Best wishes,
Andrey Murzov
the Telerik team
Is it possible to use Bing Maps instead of OpenStreet Maps?
Best,
Download and usage of the Bing map tiles besides the Bing services is illegal. It is strongly prohibited by the Microsoft Bing license agreement and we would discourage you from proceeding with this approach any further.
All the best,
Register for the Q2 2011 What's New Webinar Week. Mark your calendar for the week starting July 18th and book your seat for a walk through of all the exciting stuff we will ship with the new release!
It is hard to say what are the reasons for the erroneous behavior of your code.
The first reason for this behavior could be in using geobounds in your custom map provider. When the tiled map provider uses geobounds then for high zoom levels it could have a huge image size which will require downloading a lots of tiles. I would recommend to restrict the zoom level for this type providers. As alternative way you can consider the variant of provider without using geobounds.
Best wishes,
Andrey Murzov
the Telerik team
Thank you for being the most amazing .NET community! Your unfailing support is what helps us charge forward! We'd appreciate your vote for Telerik in this year's DevProConnections Awards. We are competing in mind-blowing 20 categories and every vote counts! VOTE for Telerik NOW >>
I was referred to this thread by Vesselin. My question/requirement is as follow:
We need to use OpenStreetMaps offline, we have the OSM data loaded into postgres, and mapnik is also running on that machine.
I have used python generate a test tile and that worked, but not sure if that is the answer?
We want the exact same functionality to be able to pan/zoom from our local server, where the tiles will reload with the higher resolution tiles. As I understand, this will be extracted from the postgres database, by mapnik, and must somehow link up with the RadMap custom provider? From the example below, it looks like the application uses downloaded png images and then displays one image?
In essence I want to host an exact duplicate of OpenStreetMaps offline, and then use my own layers.
We want to be able to display co-ordinates, and use co-ordinates to plot and do calculations and drawings, geomapping etc, all this data is in the postgres database, which is loaded from the OSM files.
We are using C# Silverlight.
Thanks
Anton
The map tile provider doesn't show 1 image. It provides RadMap with access to all necessary images. It is up to you how to implement it on "server" side: using postgre and mapnik, or just placing the images in the right folders on web-server. In both cases you have to implement custom map tile provider which will ask your "server" for map tiles by request from the RadMap control.
The RadMap functionality which shows geographically positioned elements, map shapes and so on doesn't relate to the source of the map tiles (images), but just use projection provided by map tile provider (it should be Mercator projection when OSM images are used).
Kind regards,
Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>
Thank you for the reply. I now understand how to implement the serverside, and that my issue is with getting postgis and mapnik to generate the images for me on request.
I've setup a server using the map tiles in the folder structure and that works very nicely.
Thanks
Anton
I already have a tiling system using "MapProviderBase" with MercatorProjection like Open Street Maps and google maps. Is possible to implement a tile system using other Projection? Or we just can do that with Spherical Mercator projection? I'm using the "GetTile" function:
public override Uri GetTile(int tileLevel, int tilePositionX, int tilePositionY)
Best Regards,
Gonçalo Martins
Yes, the map control allows you to use your own custom projections. You can override the SpatialReference property in your custom provider for changing its projection.
The sample code is below.
public class CustomProvider : TiledProvider
{
/// <
summary
>
/// Initializes a new instance of the CustomProvider class.
/// </
summary
>
public CustomProvider()
: base()
{
var source = new CustomSource();
this.MapSources.Add(source.UniqueId, source);
}
/// <
summary
>
/// Returns the SpatialReference for the map provider.
/// </
summary
>
public override ISpatialReference SpatialReference
{
get
{
return new CustomProjection();
}
}
}
Currently the map control contains the following projections:
- The Mercator projection EPSG:4326 (default) that refers to WGS84 as (latitude, longitude) pair coordinates in degrees
- The OSGB-1936 projection which also known as EPSG:27700
- The EPSG:900913 projection which also known as EPSG:3857 and Pseudo-Mercator projection that refers to WGS84 as (latitude, longitude) pair coordinates in meters
I would recommend you to download the source code(you can do it using your account). Please take a look at the SpatialReference, MercatorProjection, EPSG900913Projection and OSGB1936Projection classes of the DataVisualization_SL project.
You can find them at the following location:
\Controls\DataVisualization\Map\Providers\Map\SpatialReference.cs
\Controls\DataVisualization\Map\Layers\MercatorProjection.cs
\Controls\DataVisualization\Map\Projections\EPSG900913Projection.cs
\Controls\DataVisualization\Map\Projections\OSGB1936Projection.cs
I hope the source code of these methods helps you with understanding of the functionality of spatial reference.
The SpatialReference contains the GeographicToLogical and LogicalToGeographic methods. Actually they implement the Mercator projection. The EPSG900913Projection and OSGB1936Projection classes inherit the ProportionalProjection class which contains own implementation of these methods.
The map which is covered by tiles of map provider uses logical coordiantes (from 0 to 1). The GeographicToLogical and LogicalToGeographic methods implement the projection of any geographic coordinate to logical and vice versa.
Kind regards,
Andrey Murzov
the Telerik team
Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>
Hi,
I have 6 .tiles files in a zip folder in a folder called resources (not properties.Resources.resx, just a folder titled resources).Is this the right way of storing them and what do I pass into FileSystemProvider?
Hello Amy,
You can check out the following SDK example: ProvidersFileSystemMapProvider, which demonstrates a sample implementation of a FileSystemMapProvider.
I hope you find this helpful.
Regards,
Vladimir Stoyanov
Progress Telerik
Our thoughts here at Progress are with those affected by the outbreak.
Hello Amy,
I don't think that you can download the files directly in the same format. You can either organize them manually in the format used in the example or update the logic to fit your scenario.
The folders in the referenced example are organized by zoom levels. Each folder contains tiles for the corresponding zoom level. The names of the tiles are in the following format "os_{x}_{y}_{zoom}.png". The important logic to check out is in the GetTile method of the FileSystemTileSource class. It is responsible for finding the correct tile based on the format that is provided in the MainWindow.xaml.cs file.
Regards,
Vladimir Stoyanov
Progress Telerik
Our thoughts here at Progress are with those affected by the outbreak.