技术开发 频道

SQL Server 2008使用空间数据实现位置智能

对空间数据的全面支持

SQL Server 2008通过新的数据类型提供了广泛的空间支持。要理解你可以怎样使用这些数据类型来存储位置智能的数据,你首先需要了解空间数据——特别是地理数据——是怎么工作的。

空间模型

空间数据是用于显示一个表面的点、线和区域的。一般情况下,这些元素与地球上的实际物理位置有关,所以它们可以被称为地理数据。我们已经通过使用地球仪和地图熟悉了这个概念,它们一般显示了多个地理特性和它们的相对位置。
大地测量空间模型

描述一个行星表面位置的困难就在于行星不是平的。地球是一个非常复杂的对象,它可以近似的看作是一个扁椭圆体,一个(稍微)有点平坦的球体。地球的一个准确表示通常是通过地球仪来显示的,在它上面行星表面的位置是通过经度和纬度来表示的,它们是根据从赤道开始和按照相应的国际日界线所测量得到的。这个建立地理位置模型的方法被称作大地测量模型,它提供了一个定义如图1所示的地球仪上的位置和对象的精确方法。现在全球在使用几个不同的大地测量模型,包括英国的国家地图地理系统所使用的Airy 1830 椭球体,和全球的GPS解决方案所使用的WGS84 椭球体。

平面空间模型

一个大地测量模型提供了最精确的方法来显示地理特性,它使用一个椭圆体并考虑了行星的弯曲程度,这在以前人们必须使用平面地图时要计算距离是非常困难的。过去,使用二维表面或平面是非常方便的,所以在许多平面(平坦)模型中显示的一般都是基于位置的数据。现在要在一个平面二维表面使用地理数据,就要创建一个投影来展平椭球体上的地理对象。有了大地测量模型,就产生了很多用于将地球的地理特性设计到一个平坦的表面上的数学模型,包括Mercator投影、Peters投影,和Lambert Conformal

Conic投影。

无论使用哪个投影,将一个椭球体上的地理数据转换成平面表面总会导致结果地图上的地理特性方面的一些形状、尺寸或位置(或三者都有)上的失真,这就是为什么在图2中的投影中格陵兰显示如美国一般大小,而事实上它的土地面积要小很多。一般来说,投影的表面面积越大,失真就越严重——地图边缘的地方的失真程度要大于中心位置的失真程度。为此,平面模型用于较小的地理区域比较好,例如单个的国家、州和城镇,或者是没有投影的空间表面,例如内层布置图。

SQL Server 2008空间数据类型

SQL Server 2008为大地测量空间数据提供了geography数据类型,为平面空间数据提供了geometry数据类型。这两个都是Microsoft .NET Framework通用语言运行时(CLR)类型,并且可以用来存储不同种类的地理元素,例如点、线和多边形。这两个数据类型都提供了你可以用来执行空间操作的属性和方法,例如计算位置间的距离和找出两者间交叉的地理特性(例如一条河流经一个城镇。)

geography 数据类型

geography数据类型为空间数据提供了一个由经度和纬度联合定义的存储结构。使用这种数据的典型用法包括定义道路、建筑、或者地理特性如可以覆盖到一个光栅图上的向量数据,它考虑了地球的弯曲性,或者计算真实的圆弧距离和空中传播轨道,而这些在一个平面模型中所存在的固有失真引起的错误程度是不可接受的。

geometry数据类型

geometry数据类型为空间数据提供了一个存储结构,它是由任意平面上的坐标定义的。这种数据通常是用在区域匹配系统中的,例如由美国政府制定的州平面系统,或者是不需要考虑地球弯曲性的地图和内层布置图。

geometry 数据类型提供了与开放地理空间联盟(OGC)Simple Features Specification for SQL标准结合的属性和方法,使得你可以对geometry数据执行操作以产生行业标准的行为。

空间数据类型的方法

SQL Server 2008中的两种空间数据类型都提供了一组全面的实例和静态方法,你可以使用它们对空间数据执行查询和操作。例如,下面的代码示例为一个城市地图应用程序创建了两个表;一个包含了城市中区的geometry值,另一个包含了城市中的街道的geometry 值。然后一个查询获得了城市中交叉的街道和区。

CREATE TABLE Districts
    ( DistrictId
int IDENTITY (1,1),
DistrictName
nvarchar(20),
     DistrictGeo geometry);
GO
CREATE TABLE Streets
    ( StreetId
int IDENTITY (1,1),
StreetName
nvarchar(20),
     StreetGeo geometry);
GO
INSERT INTO Districts (DistrictName, DistrictGeo)
VALUES ('Downtown',
geometry::STGeomFromText
(
'POLYGON ((0 0, 150 0, 150 150, 0 150, 0 0))', 0));
INSERT INTO Districts (DistrictName, DistrictGeo)
VALUES ('Green Park',
geometry::STGeomFromText
(
'POLYGON ((300 0, 150 0, 150 150, 300 150, 300 0))', 0));
INSERT INTO Districts (DistrictName, DistrictGeo)
VALUES ('Harborside',
geometry::STGeomFromText
(
'POLYGON ((150 0, 300 0, 300 300, 150 300, 150 0))', 0));
INSERT INTO Streets (StreetName, StreetGeo)
VALUES ('First Avenue',
geometry::STGeomFromText
(
'LINESTRING (100 100, 20 180, 180 180)', 0))
GO
INSERT INTO Streets (StreetName, StreetGeo)
VALUES ('Mercator Street',
geometry::STGeomFromText
(
'LINESTRING (300 300, 300 150, 50 50)', 0))
GO
SELECT StreetName, DistrictName
FROM Districts d, Streets s
WHERE s.StreetGeo.STIntersects(DistrictGeo) = 1
ORDER BY StreetName


该查询的结果如下表所示

StreetName DistrictName    
First Avenue Downtown    
First Avenue Harborside    
Mercator Street Downtown    
Mercator Street Green Park    
Mercator Street Harborside  

 

 

0
相关文章