地图图像服务(ImageryService)提供了根据地理位置(经度和纬度)坐标和地图的缩放级别解析出对应于地图图片系统的完整地图数据元数据,包括图片映射地址、图片大小等一系列详细参数。通过该服务的服务接口也可以反向实现通过指定地理位置坐标、地图缩放级别和图片大小(高度和宽度)来生成不同的地图图片。
一、添加ImageryService的Web服务引用
微软发布的地图图像服务地址是:http://dev.virtualearth.net/webservices/v1/p_w_picpathryservice/ImageryService.svc,在项目中通过该地址添加Web服务引用后就可以使用地图图像服务中的方法进行
如上图示成功添加地图图像服务(ImageryService)后就可以使用该服务所提供的功能了,可以添加Web服务引用向导过程中生成的WCF客户端配置查看到Silverlight访问该服务的客户端完整配置信息,如下代码:
<
configuration
>
< system.serviceModel >
< bindings >
< basicHttpBinding >
< binding name ="BasicHttpBinding_IImageryService" maxBufferSize ="2147483647"
maxReceivedMessageSize ="2147483647" >
< security mode ="None" >
< transport >
< extendedProtectionPolicy policyEnforcement ="Never" />
transport >
security >
binding >
basicHttpBinding >
bindings >
< client >
< endpoint address ="http://dev.virtualearth.net/webservices/v1/p_w_picpathryservice/p_w_picpathryservice.svc"
binding ="basicHttpBinding" bindingConfiguration ="BasicHttpBinding_IImageryService"
contract ="ImageryService.IImageryService" name ="BasicHttpBinding_IImageryService" />
client >
system.serviceModel >
configuration >
< system.serviceModel >
< bindings >
< basicHttpBinding >
< binding name ="BasicHttpBinding_IImageryService" maxBufferSize ="2147483647"
maxReceivedMessageSize ="2147483647" >
< security mode ="None" >
< transport >
< extendedProtectionPolicy policyEnforcement ="Never" />
transport >
security >
binding >
basicHttpBinding >
bindings >
< client >
< endpoint address ="http://dev.virtualearth.net/webservices/v1/p_w_picpathryservice/p_w_picpathryservice.svc"
binding ="basicHttpBinding" bindingConfiguration ="BasicHttpBinding_IImageryService"
contract ="ImageryService.IImageryService" name ="BasicHttpBinding_IImageryService" />
client >
system.serviceModel >
configuration >
二、Silverlight界面布局设计
在Silverlight的界面上提供三个TextBox用于录入经度、纬度和缩放级别值,通过按钮请求调用ImageryService服务接口。
<Grid x:Name="LayoutRoot">
<m:Map CredentialsProvider="AkzZURoD0H2Sle6Nq_DE7pm7F3xOc8S3CjDTGNWkz1EFlJJkcwDKT1KcNcmYVINU" x:Name="map">m:Map>
<Border BorderBrush="Gray" BorderThickness="3,3,3,3"
Margin="3,3,3,3" HorizontalAlignment="Right"
Opacity="0.78" Height="160" Background="#A82D2D2D"
VerticalAlignment ="Top" CornerRadius="5,5,5,5">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal" Margin="3,3,3,3">
<TextBlock Text="经度:">TextBlock>
<TextBox x:Name="tbLongitude" Width="130">TextBox>
<TextBlock Text="纬度:">TextBlock>
<TextBox x:Name="tbLatitude" Width="130">TextBox>
<TextBlock Text="缩放级别:">TextBlock>
<TextBox x:Name="tbZoomLevel" Width="30">TextBox>
<Button x:Name="btnImageMetadata" Click="btnImageMetadata_Click" Content="获取图片映射地址" Margin="3">Button>
StackPanel>
<StackPanel Orientation="Horizontal" Margin="3,3,3,3">
<TextBlock Text="映射地址:">TextBlock>
<TextBox x:Name="tbMetadataResult" Width="500">TextBox>
StackPanel>
<StackPanel Orientation="Horizontal" Margin="3,3,3,3">
<TextBlock Text="图片高度:">TextBlock>
<TextBox x:Name="tbHeight" Width="150">TextBox>
<TextBlock Text="图片宽度:">TextBlock>
<TextBox x:Name="tbWidth" Width="150">TextBox>
StackPanel>
StackPanel>
Border>
Grid>
<m:Map CredentialsProvider="AkzZURoD0H2Sle6Nq_DE7pm7F3xOc8S3CjDTGNWkz1EFlJJkcwDKT1KcNcmYVINU" x:Name="map">m:Map>
<Border BorderBrush="Gray" BorderThickness="3,3,3,3"
Margin="3,3,3,3" HorizontalAlignment="Right"
Opacity="0.78" Height="160" Background="#A82D2D2D"
VerticalAlignment ="Top" CornerRadius="5,5,5,5">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal" Margin="3,3,3,3">
<TextBlock Text="经度:">TextBlock>
<TextBox x:Name="tbLongitude" Width="130">TextBox>
<TextBlock Text="纬度:">TextBlock>
<TextBox x:Name="tbLatitude" Width="130">TextBox>
<TextBlock Text="缩放级别:">TextBlock>
<TextBox x:Name="tbZoomLevel" Width="30">TextBox>
<Button x:Name="btnImageMetadata" Click="btnImageMetadata_Click" Content="获取图片映射地址" Margin="3">Button>
StackPanel>
<StackPanel Orientation="Horizontal" Margin="3,3,3,3">
<TextBlock Text="映射地址:">TextBlock>
<TextBox x:Name="tbMetadataResult" Width="500">TextBox>
StackPanel>
<StackPanel Orientation="Horizontal" Margin="3,3,3,3">
<TextBlock Text="图片高度:">TextBlock>
<TextBox x:Name="tbHeight" Width="150">TextBox>
<TextBlock Text="图片宽度:">TextBlock>
<TextBox x:Name="tbWidth" Width="150">TextBox>
StackPanel>
StackPanel>
Border>
Grid>
三、调用ImageryService服务获取地图元数据
地图图像服务(ImageryService)提供了接口实现通过地图位置经度和纬度以及地图缩放级别获取对应于地图图片系统(Tile System)的地图数据的详细信息,包括地图图片对应的Tile映射地址,图片的高度和宽度,请求图片的时间等一些列参数值,通过前面的操作以及成功添加了对ImageryService的Web服务引用,接下来只需要简单的调用服务接口就可以获取到这些数据。
private void btnImageMetadata_Click(object
sender, RoutedEventArgs e)
{
//构造服务请求对象
var request = new ImageryMetadataRequest();
request.Credentials = new Microsoft.Maps.MapControl.Credentials();
request.Credentials.ApplicationId = "AkzZURoD0H2Sle6Nq_DE7pm7F3xOc8S3CjDTGNWkz1EFlJJkcwDKT1KcNcmYVINU" ;
//设置地理位置经度、纬度和地图缩放级别,从界面控件收集值
var location = new Location(double.Parse(this.tbLatitude.Text), double.Parse(this .tbLongitude.Text));
request.Options = new ImageryMetadataOptions();
request.Options.Location = location;
request.Options.ZoomLevel = int.Parse(this .tbZoomLevel.Text);
request.Style = MapStyle.AerialWithLabels;
//构造ImageryService客户端代理对象实例
var client = new ImageryServiceClient();
client.GetImageryMetadataCompleted += (o, args) => //处理请求的响应接口
{
if (args.Error == null )
{
var response = args.Result;
this.tbMetadataResult.Text = response.Results[0 ].ImageUri.ToString();
this.tbHeight.Text = response.Results[0 ].ImageSize.Height.ToString();
this.tbWidth.Text = response.Results[0 ].ImageSize.Width.ToString();
}
};
//发起异步调用
client.GetImageryMetadataAsync(request);
}
{
//构造服务请求对象
var request = new ImageryMetadataRequest();
request.Credentials = new Microsoft.Maps.MapControl.Credentials();
request.Credentials.ApplicationId = "AkzZURoD0H2Sle6Nq_DE7pm7F3xOc8S3CjDTGNWkz1EFlJJkcwDKT1KcNcmYVINU" ;
//设置地理位置经度、纬度和地图缩放级别,从界面控件收集值
var location = new Location(double.Parse(this.tbLatitude.Text), double.Parse(this .tbLongitude.Text));
request.Options = new ImageryMetadataOptions();
request.Options.Location = location;
request.Options.ZoomLevel = int.Parse(this .tbZoomLevel.Text);
request.Style = MapStyle.AerialWithLabels;
//构造ImageryService客户端代理对象实例
var client = new ImageryServiceClient();
client.GetImageryMetadataCompleted += (o, args) => //处理请求的响应接口
{
if (args.Error == null )
{
var response = args.Result;
this.tbMetadataResult.Text = response.Results[0 ].ImageUri.ToString();
this.tbHeight.Text = response.Results[0 ].ImageSize.Height.ToString();
this.tbWidth.Text = response.Results[0 ].ImageSize.Width.ToString();
}
};
//发起异步调用
client.GetImageryMetadataAsync(request);
}
从上图可看出,通过指定的地理经度、纬度和地图缩放级别参数调用ImageryService服务接口,返回了一个地址“
http://t0.tiles.virtualearth.net/tiles/h1320.jpeg?g=409&mkt={culture}&token={token}”,该地址就是地理位置(经度:97.1964042859709,纬度:37.5939128813461),地图缩放级别为:4所对应的地图图片系统(Tile System)的地图数据映射Url,通过在浏览器中执行该Url可查看该Url对应的具体图片效果,如下图示:
上面获取到的是带地名的卫星地图,因为设置的样式是:request.Style = MapStyle.AerialWithLabels。可以通过MapStyle枚举设置不同的请求样式,比如要获取道路模式的地图则如下设置:
request.Style = MapStyle.Road;
在次通过上面获取卫星地图的地理位置坐标经度和纬度值获取下来的Url为:
http://t0.tiles.virtualearth.net/tiles/r1320.jpeg?g=409&mkt={culture}&shading=hill&token={token},其显示效果为下图所示:
四、调用ImageryService生成图片
地图图片服务(ImageryService)也提供了服务接口反向实现通过指定地理位置坐标、地图缩放级别和图片大小(高度和宽度)来生成图片。这个服务接口最终将请求转向到一个HTTP处理程序,用来根据不同的参数值生成不同的图片数据,该HTTP处理程序的请求格式:“
http://api.tiles.virtualearth.net/api/GetMap.ashx?c=纬度,经度&w=宽度&h=高度&b=h,mkt.en-US&z=4&token={token}”。
比如我们需要以中国地区地图坐标为准,生成一张地图缩放级别为10,图片高度和宽度为512的一张图片,那么完整的http请求串就应该是这样的:
http://api.tiles.virtualearth.net/api/GetMap.ashx?c=35.0521567883562,100.81816585252&w=512&h=512&b=h,mkt.en-US&z=4&token={token}
当然绝大多数情况下我们是不知道这个处理程序的路径的,只有通过调试程序才能发现最终是将请求转向到了此处理程序去完成的生成图片功能。我们在做开发的时候其实只需要关注ImageryService这个WCF服务的调用就OK了。那么要实现生成图片我们可以通过ImageryService所提供的GetMapUri()方法实现,代码如下:
private void btnGetUrl_Click(object
sender, RoutedEventArgs e)
{
var request = new MapUriRequest();
request.Credentials = new Microsoft.Maps.MapControl.Credentials();
request.Credentials.ApplicationId = "AkzZURoD0H2Sle6Nq_DE7pm7F3xOc8S3CjDTGNWkz1EFlJJkcwDKT1KcNcmYVINU" ;
request.Center = new Location(35.0521567883562,100.81816585252 );
var opt = new MapUriOptions();
opt.Style = MapStyle.AerialWithLabels;
opt.ZoomLevel = 4 ;
opt.ImageSize = new SizeOfint();
opt.ImageSize.Height = (int )imgMap.Height;
opt.ImageSize.Width = (int )imgMap.Width;
request.Options = opt;
var client = new ImageryServiceClient();
client.GetMapUriCompleted += (o, args) =>
{
var response = args.Result;
imgMap.Source = new BitmapImage(new Uri(response.Uri, UriKind.RelativeOrAbsolute));
};
client.GetMapUriAsync(request);
}
{
var request = new MapUriRequest();
request.Credentials = new Microsoft.Maps.MapControl.Credentials();
request.Credentials.ApplicationId = "AkzZURoD0H2Sle6Nq_DE7pm7F3xOc8S3CjDTGNWkz1EFlJJkcwDKT1KcNcmYVINU" ;
request.Center = new Location(35.0521567883562,100.81816585252 );
var opt = new MapUriOptions();
opt.Style = MapStyle.AerialWithLabels;
opt.ZoomLevel = 4 ;
opt.ImageSize = new SizeOfint();
opt.ImageSize.Height = (int )imgMap.Height;
opt.ImageSize.Width = (int )imgMap.Width;
request.Options = opt;
var client = new ImageryServiceClient();
client.GetMapUriCompleted += (o, args) =>
{
var response = args.Result;
imgMap.Source = new BitmapImage(new Uri(response.Uri, UriKind.RelativeOrAbsolute));
};
client.GetMapUriAsync(request);
}
上面代码段里使用了imgMap控件,这是在界面上放置的一个Image控件,通过按钮发起ImageryService的服务接口的调用,将返回的串序列为位图数据赋值给Image控件显示出来,其定义如下:
<Image x:Name="imgMap" Width="512" Height="512">Image>
通过上面的实现最终生成的图片效果如下图所示:
如果您想了解更多关于Bing Maps地图服务的知识,请查询:
MSDN:
http://msdn.microsoft.com/en-us/library/cc980922.aspx
Bing Maps开发站:
http://www.microsoft.com/maps/developers/
Bing Maps开发SDK:
http://msdn.microsoft.com/en-us/library/dd877180.aspx