Bing Maps作为通用性开发平台,无论是Silverlight还是JavaScript版本的API,都能够实现渲染其他厂商的相关地图数据,本文以实现渲染ESRI SHP格式地图数据为例,详细介绍如何在Bing Map Silverlight Control上实现Esri SHP地图数据的渲染呈现。由于BMSC不具备相应的数据读取API,需要借助第三方开源组件完成SHP收的读取,数据通过发布WCF服务提供给客户端使用。
一、开源组件
1、NetTopologySuite --地址:http://code.google.com/p/nettopologysuite/
2、GeoAPI --GeoAPI是开源项目SharpMap的一部分。
二、ESRI SHP数据读取并发布WCF服务
使用上面的开源组件API读取ESRI SHP地图数据,将里面的空间数据全部提取出来转化为WKT格式的数据通过服务发布给客户端调用即可。
1 ///
<summary>
2 /// 读取指定路径的SHP文件并返回空间对象集合
3 /// </summary>
4 /// <param name="shapepath">SHP文件路径</param>
5 /// <returns>空间对象集合</returns>
6 private IGeometryCollection ReadShape(string shapepath)
7 {
8 //判断文件是否存在
9 if (!File.Exists(shapepath))
10 throw new ArgumentException("文件 " + shapepath + " 未找到!");
11
12 //读取SHP文件的空间数据返回空间对象集合
13 ShapefileReader reader = new ShapefileReader(shapepath);
14 IGeometryCollection geometries = reader.ReadAll();
15 return geometries;
16 }
2 /// 读取指定路径的SHP文件并返回空间对象集合
3 /// </summary>
4 /// <param name="shapepath">SHP文件路径</param>
5 /// <returns>空间对象集合</returns>
6 private IGeometryCollection ReadShape(string shapepath)
7 {
8 //判断文件是否存在
9 if (!File.Exists(shapepath))
10 throw new ArgumentException("文件 " + shapepath + " 未找到!");
11
12 //读取SHP文件的空间数据返回空间对象集合
13 ShapefileReader reader = new ShapefileReader(shapepath);
14 IGeometryCollection geometries = reader.ReadAll();
15 return geometries;
16 }
使用WCF对外发布服务接口,Silverlight客户端即可非常方便的调用接口获取到数据。
1 ///
<summary>
2 /// 读取SHP地图数据并发布WCF服务
3 /// </summary>
4 /// <returns>返回空间对象的WKT</returns>
5 public List<string> GetShapeDate()
6 {
7 string shpPath = "D:\\BingMapDemo.DataService\\App_Data\\大区界线_polyline.shp";
8 IGeometryCollection collection = ReadShape(shpPath);
9
10 List<string> result = new List<string>();
11 foreach (IGeometry item in collection.Geometries)
12 {
13 //存储WKT格式空间数据
14 result.Add(item.AsText());
15 }
16 return result;
17 }
2 /// 读取SHP地图数据并发布WCF服务
3 /// </summary>
4 /// <returns>返回空间对象的WKT</returns>
5 public List<string> GetShapeDate()
6 {
7 string shpPath = "D:\\BingMapDemo.DataService\\App_Data\\大区界线_polyline.shp";
8 IGeometryCollection collection = ReadShape(shpPath);
9
10 List<string> result = new List<string>();
11 foreach (IGeometry item in collection.Geometries)
12 {
13 //存储WKT格式空间数据
14 result.Add(item.AsText());
15 }
16 return result;
17 }
三、坐标转换
因使用GeoAPI的空间对象(IGeometry)存储的空间数据格式不能完全与Bing Map Silverlight Control中的空间坐标对象完全兼容,客户端获取到数据后必须将GeoAPI的Coordinate对象转化为Bing Map Silverlight Control的Location,以兼容坐标数据的使用。
1 public
static class CoordinateConvertor
2 {
3 public static ICoordinate Convert(Location location)
4 {
5 return new Coordinate {Y = location.Latitude, X = location.Longitude};
6 }
7
8 public static Location ConvertBack(ICoordinate location)
9 {
10 return new Location {Latitude = location.Y, Longitude = location.X};
11 }
12
13 public static LocationCollection CoordinatesToLocationCollection(ICoordinate[] coordinates)
14 {
15 var locations = new LocationCollection();
16 foreach (var coordinate in coordinates)
17 {
18 locations.Add(ConvertBack(coordinate));
19 }
20 return locations;
21 }
22
23 public static ICoordinate[] LocationCollectionToCoordinates(LocationCollection locations)
24 {
25 var coordinates = new Coordinate[locations.Count];
26 for (var x = 0; x < locations.Count;x++ )
27 {
28 coordinates[x] = (Coordinate)Convert(locations[x]);
29 }
30 return (ICoordinate[])coordinates;
31 }
32
33 public static LocationCollection LocationRectToLocationCollection(LocationRect locationRect)
34 {
35 var locations = new LocationCollection
36 {
37 locationRect.Northwest,
38 locationRect.Southwest,
39 locationRect.Southeast,
40 locationRect.Northeast,
41 locationRect.Northwest
42 };
43 return locations;
44 }
45 }
2 {
3 public static ICoordinate Convert(Location location)
4 {
5 return new Coordinate {Y = location.Latitude, X = location.Longitude};
6 }
7
8 public static Location ConvertBack(ICoordinate location)
9 {
10 return new Location {Latitude = location.Y, Longitude = location.X};
11 }
12
13 public static LocationCollection CoordinatesToLocationCollection(ICoordinate[] coordinates)
14 {
15 var locations = new LocationCollection();
16 foreach (var coordinate in coordinates)
17 {
18 locations.Add(ConvertBack(coordinate));
19 }
20 return locations;
21 }
22
23 public static ICoordinate[] LocationCollectionToCoordinates(LocationCollection locations)
24 {
25 var coordinates = new Coordinate[locations.Count];
26 for (var x = 0; x < locations.Count;x++ )
27 {
28 coordinates[x] = (Coordinate)Convert(locations[x]);
29 }
30 return (ICoordinate[])coordinates;
31 }
32
33 public static LocationCollection LocationRectToLocationCollection(LocationRect locationRect)
34 {
35 var locations = new LocationCollection
36 {
37 locationRect.Northwest,
38 locationRect.Southwest,
39 locationRect.Southeast,
40 locationRect.Northeast,
41 locationRect.Northwest
42 };
43 return locations;
44 }
45 }
四、渲染SHP空间数据
SHP文件中的空间数据通过WCF以WK的格式发布到客户端,客户端通过读取WKT为GeoAPI的空间对象,然后通过坐标转换将坐标转化为Bing Map Silverlight Control所兼容的坐标数据格式,数据在客户端以多边形的方式进行渲染呈现。
1 private
void ShpMapReader()
2 {
3 GeometryServiceClient service = new GeometryServiceClient();
4 service.GetShapeDateCompleted += service_GetShapeDateCompleted;
5 service.GetShapeDateAsync();
6 }
7
8 private void service_GetShapeDateCompleted(object sender, GetShapeDateCompletedEventArgs e)
9 {
10 if (e.Error == null)
11 {
12 ObservableCollection<string> result = e.Result;
13 WKTReader reader = null;
14 foreach (var item in result)
15 {
16 reader = new WKTReader();
17 //读取WKT到空间对象
18 IGeometry geometry = reader.Read(item);
19 if (geometry == null) continue;
20 //边界
21 MapPolygon line = new MapPolygon();
22 //转换坐标
23 line.Locations = CoordinateConvertor.CoordinatesToLocationCollection(geometry.Coordinates);
24 line.Fill = new SolidColorBrush(Colors.Gray);
25 line.BorderBrush = new SolidColorBrush(Colors.Green);
26 line.BorderThickness = new Thickness(2);
27 line.MouseEnter += new MouseEventHandler(line_MouseEnter);
28 line.MouseLeave += new MouseEventHandler(line_MouseLeave);
29 this.mlayer.Children.Add(line);
30 }
31 }
32 }
2 {
3 GeometryServiceClient service = new GeometryServiceClient();
4 service.GetShapeDateCompleted += service_GetShapeDateCompleted;
5 service.GetShapeDateAsync();
6 }
7
8 private void service_GetShapeDateCompleted(object sender, GetShapeDateCompletedEventArgs e)
9 {
10 if (e.Error == null)
11 {
12 ObservableCollection<string> result = e.Result;
13 WKTReader reader = null;
14 foreach (var item in result)
15 {
16 reader = new WKTReader();
17 //读取WKT到空间对象
18 IGeometry geometry = reader.Read(item);
19 if (geometry == null) continue;
20 //边界
21 MapPolygon line = new MapPolygon();
22 //转换坐标
23 line.Locations = CoordinateConvertor.CoordinatesToLocationCollection(geometry.Coordinates);
24 line.Fill = new SolidColorBrush(Colors.Gray);
25 line.BorderBrush = new SolidColorBrush(Colors.Green);
26 line.BorderThickness = new Thickness(2);
27 line.MouseEnter += new MouseEventHandler(line_MouseEnter);
28 line.MouseLeave += new MouseEventHandler(line_MouseLeave);
29 this.mlayer.Children.Add(line);
30 }
31 }
32 }
Bing Maps中渲染ESRI SHP空间数据的实现非常简单,掌握了应用开源组件对数据进行读取就OK,以下是运行的效果图。
五、相关资源:
[1]、SharpMap:http://sharpmap.codeplex.com
[2]、NetTopologySuite:http://code.google.com/p/nettopologysuite
[3]、WKT:http://www.opengis.org/techno/specs.htm