Bing Maps開(kāi)發(fā)擴(kuò)展:Oracle Spatial的空間數(shù)據(jù)渲染
Oracle Spatial的空間數(shù)據(jù)應(yīng)用和微軟SQL Server 2008的大同小異,SQL Server 2008提供了基于SQLCLR的編程支持,Oracle Spatial暫時(shí)還沒(méi)有比較完善的組件支持。在實(shí)際開(kāi)發(fā)應(yīng)用中我們可以選擇折中的解決方案,比如將空間數(shù)據(jù)讀取為通用的空間數(shù)據(jù)表達(dá)格式(如:WKT),利用開(kāi)源的WKT讀取組件便可將WKT數(shù)據(jù)解析為對(duì)應(yīng)的空間數(shù)據(jù)坐標(biāo)點(diǎn)或坐標(biāo)集合。
下面以一個(gè)實(shí)際的案例來(lái)介紹如何讀取Oracle Spatial數(shù)據(jù)為WKT,并通過(guò)WKT組件解析數(shù)據(jù),最終在Bing Maps中進(jìn)行渲染,F(xiàn)要實(shí)現(xiàn)將數(shù)據(jù)庫(kù)中地市表配置的全國(guó)地市數(shù)據(jù)中四川省的數(shù)據(jù)讀取出來(lái)在地圖中進(jìn)行渲染,Oracle Spatial的sdo_geometry數(shù)據(jù)類型則可以直接使用函數(shù)(get_wkt())進(jìn)行轉(zhuǎn)換為clob數(shù)據(jù)類型數(shù)據(jù)。
select t.areacode,t.areaname, (t.area.get_wkt()) wkt from areainfo t where areacode like '8623%'
為了方便客戶端的使用,服務(wù)端可以通過(guò)WCF服務(wù)封裝數(shù)據(jù)為數(shù)組返回,以下為地市實(shí)體對(duì)象數(shù)據(jù)結(jié)構(gòu)和WCF服務(wù)的定義。
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客戶端調(diào)用WCF服務(wù)以獲取數(shù)據(jù)庫(kù)中的數(shù)據(jù),這里就不做詳細(xì)介紹。在這里需要特別介紹的是幾個(gè)開(kāi)源應(yīng)用:
1、SharpMap開(kāi)源的GeoAPI.
2、NetTopologySuite.
這兩個(gè)開(kāi)源庫(kù)分別定義好了不同GIS坐標(biāo)系的空間標(biāo)準(zhǔn),以及基于地理空間的空間對(duì)象、空間計(jì)算和空間分析接口,在應(yīng)用開(kāi)發(fā)中可以非常方便的完成空間數(shù)據(jù)的讀寫(xiě)、驗(yàn)證、計(jì)算和分析功能。本文使用到了WKT讀取組件(WKTReader),可以實(shí)現(xiàn)將WKT格式的字符串解析為符合GIS坐標(biāo)系標(biāo)準(zhǔn)的通用空間對(duì)象(Geometry),此空間對(duì)象中就包含了完整的WKT數(shù)據(jù)的描述,如WKT所表示的坐標(biāo)點(diǎn),坐標(biāo)點(diǎn)集合,內(nèi)部坐標(biāo)點(diǎn),空間面積等等。
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);
}
}
通過(guò)WKTReader將WKT格式的空間數(shù)據(jù)解析為IGeometry接口的空間對(duì)象,就可以非常方便的獲取WKT空間數(shù)據(jù)中的各種坐標(biāo)值。如果上面所獲取到的數(shù)據(jù),我們就可以通過(guò)繪制多邊形以及通過(guò)自定義標(biāo)注將數(shù)據(jù)渲染在地圖中。
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);
//名稱標(biāo)注
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);
}