Oracle Spatial的空间数据应用和微软SQL Server 2008的大同小异,SQL Server 2008提供了基于SQLCLR的编程支持,Oracle Spatial暂时还没有比较完善的组件支持。在实际开发应用中我们可以选择折中的解决方案,比如将空间数据读取为通用的空间数据表达格式(如:WKT),利用开源的WKT读取组件便可将WKT数据解析为对应的空间数据坐标点或坐标集合。
下面以一个实际的案例来介绍如何读取Oracle Spatial数据为WKT,并通过WKT组件解析数据,最终在Bing Maps中进行渲染。现要实现将数据库中地市表配置的全国地市数据中四川省的数据读取出来在地图中进行渲染,Oracle Spatial的sdo_geometry数据类型则可以直接使用函数(get_wkt())进行转换为clob数据类型数据。
select t.areacode,t.areaname, (t.area.get_wkt()) wkt from areainfo t where areacode like '8623%'
为了方便客户端的使用,服务端可以通过WCF服务封装数据为数组返回,以下为地市实体对象数据结构和WCF服务的定义。
namespace OracleSpatial.DataService.Models
{
[DataContract]
public class AreaInfo
{
[DataMember]
public string AreaCode { get; set; }
[DataMember]
public string AreaName { get; set; }
[DataMember]
public string WKT { get; set; }
}
}
namespace OracleSpatial.DataService
{
[ServiceContract]
public interface IGeometryService
{
[OperationContract]
List GetAreaInfo();
}
}
Bing Maps的Silverlight客户端调用WCF服务以获取数据库中的数据,这里就不做详细介绍。在这里需要特别介绍的是几个开源应用:
1、SharpMap开源的GeoAPI.
2、NetTopologySuite.
这两个开源库分别定义好了不同GIS坐标系的空间标准,以及基于地理空间的空间对象、空间计算和空间分析接口,在应用开发中可以非常方便的完成空间数据的读写、验证、计算和分析功能。本文使用到了WKT读取组件(WKTReader),可以实现将WKT格式的字符串解析为符合GIS坐标系标准的通用空间对象(Geometry),此空间对象中就包含了完整的WKT数据的描述,如WKT所表示的坐标点,坐标点集合,内部坐标点,空间面积等等。
public MainPage()
{
InitializeComponent();
this.Loaded += (sender, e) =>
{
LoadChinaMap();
GeometryServiceClient service = new GeometryServiceClient();
service.GetAreaInfoCompleted += service_GetAreaInfoCompleted;
service.GetAreaInfoAsync();
};
}
private void service_GetAreaInfoCompleted(object sender, GetAreaInfoCompletedEventArgs e)
{
if (e.Error == null)
{
ObservableCollection result = e.Result;
WKTReader reader = reader = new WKTReader();
IGeometry geometry = reader.Read(result[0].WKT);
}
}
通过WKTReader将WKT格式的空间数据解析为IGeometry接口的空间对象,就可以非常方便的获取WKT空间数据中的各种坐标值。如果上面所获取到的数据,我们就可以通过绘制多边形以及通过自定义标注将数据渲染在地图中。
private void service_GetAreaInfoCompleted(object sender, GetAreaInfoCompletedEventArgs e)
{
if (e.Error == null)
{
ObservableCollection result = e.Result;
WKTReader reader = null;
foreach (var item in result)
{
reader = new WKTReader();
IGeometry geometry = reader.Read(item.WKT);
//边界
MapPolygon line = new MapPolygon();
line.Locations = CoordinateConvertor.CoordinatesToLocationCollection(geometry.Coordinates);
line.Fill = new SolidColorBrush(Colors.Gray);
line.BorderBrush = new SolidColorBrush(Colors.Green);
line.BorderThickness = new Thickness(2);
line.MouseEnter += new MouseEventHandler(line_MouseEnter);
line.MouseLeave += new MouseEventHandler(line_MouseLeave);
this.mlayer.Children.Add(line);
//名称标注
this.mlayer.AddChild(new PointControl(item.AreaName),
new Microsoft.Maps.MapControl.Location(geometry.InteriorPoint.Y, geometry.InteriorPoint.X));
}
}
}
private void line_MouseLeave(object sender, MouseEventArgs e)
{
MapPolygon mp = sender as MapPolygon;
mp.Fill = new SolidColorBrush(Colors.Gray);
}
private void line_MouseEnter(object sender, MouseEventArgs e)
{
MapPolygon mp = sender as MapPolygon;
mp.Fill = new SolidColorBrush(Colors.Yellow);
}