OSM(OpenStreetMap-开放街道地图)服务就是一种发布自己地图数据图片为服务的一种实现类型,开放街道地图成立动机在于希望能创造并且提供可以被自由地使用的地理资料(像街道地图)给每个想使用的人,就像自由软体所赋予使用者的自由一样,本篇将介绍如何在Bing Maps Silverlight Control开发中去使用OSM发布的地图服务。
要在Bing Maps Silverlight Control中集成OSM地图是非常简单的,其实无论什么地图都是以地图服务的形式发布出来的,隐藏在其后的都有一套Tile算法,最终在客户端呈现地图则根据具体的Tile映射系统的算法可确定客户端呈现的时候以何种请求的加载出地图数据。实际上要在Bing Maps中集成OSM,也就是通过自定义TileSource来实现,为所需要集成的OSM自定义一个TileSource,专门用于加载此OSM地图数据。关于Bing Maps的TileSystem可查阅我的另一篇博文:《
【Silverlight】Bing Maps学习系列(七):使用Bing Maps的图片系统(Tile System)》,里面有对TileSystem的简单应用示例,还有两篇详细介绍Bing Maps的Tile System的博文连接。
在Bing Maps Silverlight Controls开发中,实现自定义的TileSource有多种方式,可以直接继承Bing Maps Silverlight Controls内置的TileSource实现无范围限制的图层加载,也可以继承于LocationRectTileSource类实现定制范围的地图图层加载,这里以LocationRectTileSource为例演示自定义TileSource加载指定范围的OSM(
http://www.openstreetmap.org/)地图数据。
public
class
OpenStreetMapTileSource : LocationRectTileSource
{
private const string TilePathMapnik = @" http://{S}.tile.openstreetmap.org/{Z}/{X}/{Y}.png " ;
private readonly Random _Rand = new Random();
private readonly string [] TilePathPrefixes = new [] { " a " , " b " , " c " , " d " , " e " , " f " };
public OpenStreetMapTileSource()
: base (TilePathMapnik,
new LocationRect( new Location( 60 , 60 ), new Location( 13 , 140 )),
new Range < double > ( 1 , 17 ))
{ }
public override Uri GetUri( int x, int y, int zoomLevel)
{
string prefix = TilePathPrefixes[_Rand.Next( 6 )];
string url = this .UriFormat;
url = url.Replace( " {S} " , prefix);
url = url.Replace( " {Z} " , zoomLevel.ToString());
url = url.Replace( " {X} " , x.ToString());
url = url.Replace( " {Y} " , y.ToString());
return new Uri(url);
}
}
{
private const string TilePathMapnik = @" http://{S}.tile.openstreetmap.org/{Z}/{X}/{Y}.png " ;
private readonly Random _Rand = new Random();
private readonly string [] TilePathPrefixes = new [] { " a " , " b " , " c " , " d " , " e " , " f " };
public OpenStreetMapTileSource()
: base (TilePathMapnik,
new LocationRect( new Location( 60 , 60 ), new Location( 13 , 140 )),
new Range < double > ( 1 , 17 ))
{ }
public override Uri GetUri( int x, int y, int zoomLevel)
{
string prefix = TilePathPrefixes[_Rand.Next( 6 )];
string url = this .UriFormat;
url = url.Replace( " {S} " , prefix);
url = url.Replace( " {Z} " , zoomLevel.ToString());
url = url.Replace( " {X} " , x.ToString());
url = url.Replace( " {Y} " , y.ToString());
return new Uri(url);
}
}
如上代码块就是为OSM(
http://www.openstreetmap.org/)地图自定义的TileSource,接下来只需要在程序中制定地图的MapTileLayer的源为该TileSource就能实现加载OSM的地图,实现OSM地图与Bing Maps集成了。
<
m:Map
x:Name
="map"
Margin
="0,0,0,0"
CredentialsProvider
="
{StaticResource MyCredentials}
"
ScaleVisibility ="Visible"
CopyrightVisibility ="Collapsed" >
< m:MapTileLayer x:Name ="OSMTileLayer" ></ m:MapTileLayer >
</ m:Map >
ScaleVisibility ="Visible"
CopyrightVisibility ="Collapsed" >
< m:MapTileLayer x:Name ="OSMTileLayer" ></ m:MapTileLayer >
</ m:Map >
可以通过在XAML中直接给地图(Map)添加一个MapTileLayer,用于加载指定的TileSource的地图,也可以在程序中动态构造MapTileLayer,两种方式实现的效率是一样的。如上代码块是通过直接在XAML代码中加入的MapTileLayer图层,那么可以通过如下方式设置该Tile图层的源,去加载OSM地图。
OSMTileLayer.TileSources.Add(
new
OpenStreetMapTileSource());
编译项目运行可以看到成功的将OSM地图集成进了Bing Maps中,详细如下图所示:
需要注意的是OSM也有很多种,在自定义OSM的Tile加载算法得时候得根据所要集成的不同OSM地图进行编写,比如下面的自定义加载OSM地图的TileSource定义:
///
<summary>
/// 自定义OSM地图服务的TileSource
/// </summary>
public class OSMTileSource : LocationRectTileSource
{
public OSMTileSource()
: base ( @" http://az1923.vo.msecnd.net/osm/{2}/{0}/{1}.png " ,
new LocationRect( new Location( - 19.047 , 47.379 ), new Location( - 18.733 , 47.645 )),
new Range < double > ( 1 , 17 ))
{
}
/// <summary>
/// 重写Tile算法
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="zoomLevel"></param>
/// <returns></returns>
public override Uri GetUri( int x, int y, int zoomLevel)
{
return new Uri( string .Format( this .UriFormat, x, y, zoomLevel), UriKind.RelativeOrAbsolute);
}
}
/// 自定义OSM地图服务的TileSource
/// </summary>
public class OSMTileSource : LocationRectTileSource
{
public OSMTileSource()
: base ( @" http://az1923.vo.msecnd.net/osm/{2}/{0}/{1}.png " ,
new LocationRect( new Location( - 19.047 , 47.379 ), new Location( - 18.733 , 47.645 )),
new Range < double > ( 1 , 17 ))
{
}
/// <summary>
/// 重写Tile算法
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="zoomLevel"></param>
/// <returns></returns>
public override Uri GetUri( int x, int y, int zoomLevel)
{
return new Uri( string .Format( this .UriFormat, x, y, zoomLevel), UriKind.RelativeOrAbsolute);
}
}
通过和上面集成OSM()地图的TileSource的算法是不同的,加载地图的Tile算法主要取决于发布OSM地图的Tile映射。上面代码块中的定义指定的加载地图图层的范围也不在是中国地区范围了,下图为最终运行效果截图:
最近很多朋友都在问我一个问题,要如何才能发布自己的图片为地图服务,然后加载到地图组件中呈现出来?其实要实现这一功能点是可以的,当然实现这一功能也是痛苦的,首先得了解常用、常见或是一些比较通用的GIS相关的概论和知识体系,了解相关的技术原理和工具的使用后就可以将自己的图片发布为OSM的地图服务,通过本文所介绍的方式就可以加载到Bing Maps中呈现了。
本文转自 beniao 51CTO博客,原文链接:http://blog.51cto.com/beniao/291108,如需转载请自行联系原作者