在地图上绘制点
现在你已经知道如何从数据库读取一个点的值,接下来可以做更有趣的事情了,如在地图上绘制该点。在web上,有许多地图服务提供商,如谷歌,微软等。
如果你采用微软的方案,必应地图提供了一个选择,当必应显示你的地图时,它使用类似下面的URL创建图像:
在这个例子中,查询字符串cp后指定了经纬度值-119.5和37.8,有了这个信息,你可以使用下面的代码构造URL:
SqlGeography geog = ReadPointFromDatabase(id);
string bingMapsFormat =
"http://www.bing.com/maps/default.aspx?" +
"v=2&FORM=LMLTCC&cp={0}~{1}&style=r&lvl=8";
string bingMapsUrl = string.Format(
bingMapsFormat, geog.Lat, geog.Long);
webBrowser1.Navigate(bingMapsUrl);
MessageBox.Show("Point " + geog.Lat +
", " + geog.Long + " plotted!");
这里的ReadPointFromDatabase方法可以从数据库中根据id检索SqlGeography对象,接下来的代码构造了必要的URL值,然后使用一个简单的WinForms WebBrowser组件显示包含了地图的网页,如图4所示。
当然,更好的实现应该使用真实的地图控件,并在地图顶部增加地图操作按钮,但对于许多简单的应用,能够以某点为中心显示地图已经足够了。
多边形计算实例
到目前为止,我们已经讨论了geometry和geography类型,但仅讨论了单点情况,虽然二维空间的点非常有用,但如果能存储一条线,或一个多边形在数据库中不是更有用吗?好消息是你可以做到!
还是以SqlGeometry为例,使用静态Point方法,你可以将一个点存储到对象中,但同一个类中也包含创建线和多边形的方法,如图5所示。因此每个SqlGeometry对象(或一个SqlGeography对象)可以存储一到多个点,你可以使用这些点形成任何你想要的对象。

图 5 SqlGeometry类的方法
例如,假设你要存储一条直线,这需要两个点:起点和终点,你可以使用两个字段来分别存储起点和终点,但SQL Server 2008允许你在一个geometry数据类型中存储这两个点,你可能会开始思考在一个表字段中存储一到多个点会有什么好处,其中一个原因就是存储效率,另一个就是计算,是的,SQL Server和对应的.Net对象类型允许你执行计算。
你可能想用存储在数据库中的多个点组成一个多边形,如一个正方形,然后你可能需要确定另一个点是否也在这个正方形范围内,解决起来也很简单,可以使用C#代码实现,也可以直接通过SQL Server的功能实现。
除了判断点是否存在等简单应用外,SQL Server也支持更多的高级特性,例如,你可以计算区域,找出对象的中心位置,检查多边形是否闭合,或者找出多边形上的点数。这为你提供了无限可能,特别要提出的是你既可以在代码中使用SqlGeometry和SqlGeography对象实现,又可以直接在存储过程的函数中实现。
我们还是以正方形为例,我们的目标是监测某个点是否在该正方形范围内,首先使用直角坐标系((0,0), (0,10), (10,10), (10,0))定义一个正方形,然后确定点(5,5)是否在该正方形内,如图6所示,你如何使用SqlGeometry .Net类实现这个测试呢?

图 6 这个点在正方形内吗?
首先你需要定义你的正方形,在.Net中你可以使用StringBuilder组件,或者使用SqlGeometryBuilder对象构建几何对象,下面是使用这个类的例子:
builder.SetSrid(0);
builder.BeginGeometry(OpenGisGeometryType.Polygon);
builder.BeginFigure(0, 0);
builder.AddLine(0, 10);
builder.AddLine(10, 10);
builder.AddLine(10, 0);
builder.AddLine(0,0);
builder.EndFigure();
builder.EndGeometry();
在这里,SqlGeometryBuilder(Microsoft.SqlServer.Types命名空间的一部分)使用四个点构造了一个正方形,但因为你可以在多个不同的对象中存储不受数量限制的点,你必须在开始和结束时指定一个数字,在此之前,你需要指定空间参考id(SRID),以及你使用BeginGeometry方法创建的对象类型,虽然SRID的值可以忽略,但SRID必须指定,因此0是非常好的选择。
现在已经定义好正方形,现在该检查那个点是否在正方形内了,这可以使用SqlGeometry对象的STContains方法实现,但首先需要创建一个几何对象的实例,可以使用ConstructedGeometry属性完成,如:
SqlGeometry point = SqlGeometry.Point(5, 5, 0);
SqlBoolean contains = square.STContains(point);
if (contains.Value)
{
MessageBox.Show("Contains point!");
}
你可能已猜到,上面的代码会显示一条消息,显示点(5,5)在该正方形内,实际上这一点是正方形的中心点。
小结
SQL Server 2008支持许多有趣的新特性,其中一个就是支持空间数据,通过阅读本文,你应该已经了解了geometry和geography类型,并看到了如何在C#应用程序中使用这些类型,如如何读写数据点,以及如何利用经纬度值在地图上显示一个点。
虽然使用浮点字段也可以存储经纬度值,但SQL Server 2008让这一切都变得更加简单了,表中的每个geometry或geography数据类型都可以存储一到多个点,因此可以形成任意复杂的多边形,这种支持让你可以在数据库表中只创建一个字段,就可以存储多个点的数据,如果利用浮点字段是很难办到的。
新的空间数据类型另一个好处是你可以利用这些值进行计算,SQL Server 2008为各种不同的计算提供了良好的支持,相信下一个SQL Server版本会这方面进行增强。