目录
MySQL支持空间扩展,允许生成、保存和分析地理特征。这些特征可用于MyISAM、InnoDB、NDB、BDB和ARCHIVE表(但是,ARCHIVE引擎不支持索引功能,因此,不能为ARCHIVE列中的空间列编制索引)。
本章介绍了下述议题:
· OpenGIS几何模型中这些空间扩展的基础。
· 用于表示空间数据的数据格式。
· 如何在MySQL中使用空间数据。
· 使用关于空间数据的索引功能。
· MySQL与OpenGIS规范的差异。
如果在MySQL空间扩展的使用方面有任何问题,可在我们网站的GIS论坛中讨论。
遵从OpenGIS联盟(OGC)的规范,MySQL实施了空间扩展。OGC是一个由250多家公司、代理机构和大学参与的国际联盟,负责开发公开的概念解决方案,这类解决方案对所有用来管理空间数据的应用都是有用的。OGC的网站是http://www.opengis.org/。
1997年,OpenGIS联盟(OGC)发布了针对SQL的OpenGISR简单特征规范,在该文档中,提出了扩展SQL RDBMS以支持空间数据的一些概念性方法。该规范可从OpenGIS网站上获得http://www.opengis.org/docs/99-049.pdf。其中包含与本章有关的额外信息。
MySQL实施了OGC建议的具有Geometry类型的SQL环境的一个子集。该术语指的是用一组集合类型扩展的环境。具有几何值的SQL列是作为拥有集合类型的列实施的。该规范描述了SQL几何类型集合,以及作用在这些类型上用于创建和分析几何值的函数。
地理特征指的是世界上具有地理位置的任何事物。它可以是:
· 实体,如山、池溏、城市。
· 空间,如邮政区域、热带。
· 可定义的位置,如两条街道相交的十字路口。
有些文件采用术语地理空间特征来指代地理特征。
几何是另一个表示地理特征的术语。最初,单词几何表示的是对大地的测量。来自制图学的另一个含义指的是制图人员用于绘制世界地图的地理特征。
本章将所有这些术语当作同义词对待:地理特征、地理空间特征、或几何。最常使用的术语是几何。
我们将几何定义为世界上具有地理位置的点或点的集合。
OGC具有几何类型的SQL环境建议的几何类型集合,基于OpenGIS几何模型。在本模型中,每个几何对象均具有下述一般属性:
· 与空间参考系统相关,其中介绍了定义对象的坐标空间。
· 属于某种几何类。
几何类定义了下述层次:
· Geometry(非实例化)
o Point(可实例化的)
o Curve(非实例化)
§ LineString(可实例化的)
· Line
· LinearRing
o Surface(非实例化)
§ Polygon(可实例化的)
o GeometryCollection(可实例化的)
§ MultiPoint(可实例化的)
§ MultiCurve(非实例化)
· MultiLineString(可实例化的)
§ MultiSurface(非实例化)
· MultiPolygon(可实例化的)
不能在非实例化类中创建对象。能够在可实例化类中创建对象。所有类均有属性,可实例化类还可以包含声明(定义有效类实例的规则)。
Geometry是一种基本类。它是一种抽象类。Geometry的可实例化子类限制为可在2维坐标空间中存在的0、1、2维几何对象。所有的可实例化几何类是这样定义的,从而使得几何类的实例从拓扑意义上讲是闭合的(也就是说,所有定义的几何类包含其边界)。
基本Geometry类具有关于Point、Curve、Surface和GeometryCollection的子类:
· Point表示0维对象。
· Curve表示1维对象,具有子类LineString,以及次级子类Line和LinearRing。
· Surface是为2维对象设计的,具有子类Polygon。
· GeometryCollection具有特殊的0维、1维和2维类集合,名为MultiPoint、MultiLineString和MultiPolygon,分别用于为对应的Points、LineStrings和Polygons集合进行几何建模。MultiCurve和MultiSurface是作为抽象超类引入的,它们归纳了用于处理Curves和Surfaces的集合接口。
Geometry、Curve、Surface、MultiCurve和MultiSurface定义为非实例化类。它们为其子类定义了公用方法集合,而且是为扩展而包含在内的。
Point、LineString、Polygon、GeometryCollection、MultiPoint、MultiLineString和MultiPolygon定义为可实例化类。
Geometry是层次结构的根类。它是一种非实例化类,但具有很多属性,这些属性对由任何Geometry子类创建的所有几何值来说是共同的。下面介绍了这些属性(尤其是具有自己特殊属性的子类)。
Geometry属性
Geometry值具有下述属性:
· 其type(类型)。每个geometry属于层次结构中可实例化类之一。
· 其SRID,或空间参考ID。该值确定了用于描述定义几何对象的坐标空间的空间坐标系统。
在MySQL中,SRID值仅是与geometry值相关的整数值。所有计算均是在欧几里得几何系(平面)中进行的。
· 它在其空间坐标系统中的coordinates(坐标),表示为双精度数值(8字节)。所有的非空几何对象至少包含一对坐标(X、Y)。空几何对象不含坐标。
坐标与SRID相关。例如,在不同的坐标系内,两个对象之间的距离会有所不同,即使这两个对象具有相同的坐标也同样。这是因为,平面坐标系中的距离和地心坐标系(地球表面上的坐标)中的距离是不同的事项。
· 其interior(内部)、boundary(边界)和exterior(外部)。
每个几何对象均占据空间中的某一位置。几何对象的exterior(外部)指的是未被该对象占据的所有空间。其interior(内部)指的是被该对象占据的空间。其boundary(边界)指的是几何对象内部和外部之间的界面。
· 其MBR(最小边界矩形)或包络面。这是一种边界几何值,由最小和最大坐标(X,Y)构成。
· ((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))
· 无论值是简单的或非简单的。类型(LineString、MultiPoint、MultiLineString)的几何值或是简单的,或是非简单的。每个类型决定了其自己的简单或非简单声明。
· 无论值是封闭的或非封闭的。类型(LineString、MultiPoint)的几何值或是封闭的,或是非封闭的。每个类型决定了其自己的封闭或非封闭声明。
· 无论值是空的或非空的。如果没有任何点,几何对象是空的。空几何对象的内部、外部和边界未定义(也就是说,它们由Null值表示)。空的几何对象定义为总是简单的,面积为0。
· 其dimension(维数)。几何对象的维数为−1、0、1或2:
o −1用于空几何对象。
o 0用于无长度、无面积的几何对象。
o 1用于具有非0长度和0面积的几何对象。
o 2用于具有非0面积的几何对象。
Point对象的维数为0。LineString对象的维数为1。Polygon对象的维数为2。MultiPoint、MultiLineString和MultiPolygon对象的维数与构成它们的元素的维数相同。
Point(点)指的是代表坐标空间中单个位置的几何类。
Point示例
· 想像一张具有众多城市的大世界地图。每个Point对象可代表1个城市。
· 在城市地图上,Point对象可代表1个公共汽车站。
Point属性
· X-坐标值。
· Y-坐标值。
· Point定义为0维几何对象。
· Point的边界为空集合。
Curve(曲线)是一种1维几何对象,通常由一系列点表示。Curve的特殊子类定义了点之间的内插类型。Curve是一种非实例化类。
Curve属性
· Curve具有其点的坐标。
· Curve定义为1维几何对象。
· 如果未通过相同的点两次,Curve就是简单的。
· 如果其起点等于其终点,Curve就是封闭的。
· 封闭Curve的边界为空。
· 非封闭Curve的边界由其两个端点构成。
· 简单且封闭的Curve是LinearRing。
LineString是具有点之间线性内插特性的Curve。
LineString示例
· 在世界地图上,LineString对象可表示河流。
· 在城市地图上,LineString对象可表示街道。
LineString属性
· LineString具有线段的坐标,由每个连续的点对(两点)定义。
· 如果仅包含两点,LineString为Line。
· 如果它既是简单的也是封闭的,LineString为LinearRing。
Surface是一种2维几何对象。它是一种非实例化类。其唯一的可实例化子类是Polygon.
Surface属性
· Surface定义为2维几何对象。
· 在OpenGIS规范中,将简单的Surface定义为由单一“patch”构成的几何对象,它与单个外部边界以及0或多个内部边界有关。
· 简单Surface的边界是一组与其内部和外部边界对应的封闭曲线的集合。
Polygon是代表多边几何对象的平面Surface。它由单个外部边界以及0或多个内部边界定义,其中,每个内部边界定义为Polygon中的1个孔。
Polygon示例
· 在地区地图上,Polygon对象可表示森林、区等。
Polygon声明
· Polygon的边界由一组构成其外部边界和比内部边界的LinearRing归向集合构成(即,简单且封闭的LineString对象)。
· Polygon没有交叉的环。Polygon边界中的环可能会在Point处相交,但仅以切线方式相交。
· Polygon没有线、尖峰或穿孔。
· Polygon有由连接点集合构成的内部。
· Polygon可能包含孔。对于具有孔的Polygon,其外部不连接。每个孔定义了连接的外部部件。
前述声明使得Polygon成为简单的几何对象。
MultiCurve属性
· MultiCurve是1维几何对象。
· 当且仅当其所有元素均是简单的时,MultiCurve才是简单的。任意两元素的唯一交叉仅出现在两元素边界的点上。
· MultiCurve边界是通过采用“模2联合规则”(也称为奇偶规则)获得的:如果某一点位于奇数编号MultiCurve元素的边界内,它将位于MultiCurve的边界内。
· 如果其所有元素均是封闭的,则MultiCurve为封闭的。
· 封闭MultiCurve的边界总为空。
19.2.11. 类MultiLineString
MultiPolygon示例
· 在地区地图上,MultiPolygon可表示湖泊系统。
MultiPolygon声明
· MultiPolygon没有内部相交的的2个Polygon元素。
· MultiPolygon没有2个交叉的Polygon元素(前述声明也禁止交叉),也没有在无数点处相接触的2个Polugon元素。
· MultiPolygon不能含有有断开的线、尖峰或穿孔。MultiPolygon是一种正常的封闭点集合。
· 对于有1个以上Polygon元素的MultiPolygon,具有不连接的内部。MultiPolygon内部已连接部件的数目等于MultiPolygon中Polygon值的数目。
MultiPolygon属性
· MultiPolygon是2维几何对象。
· MultiPolygon边界是与其Polygon元素的边界对应的封闭曲线集合(LineString值)。
· MultiPolygon边界中的每个Curve准确位于1个Polygon元素的边界内。
· Polygon元素边界中的每个Curve位于MultiPolygon的边界中。
19.3. 支持的空间数据格式
几何对象WKT表示的示例:
· Point:
· POINT(15 20)
注意,指定点坐标时不使用分隔用逗号。
· 具有4个点的LineString:
· LINESTRING(0 0, 10 10, 20 25, 50 60)
注意,点坐标对采用逗号隔开。
· 具有1个外部环和1个内部环的Polygon:
· POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))
· 具有三个Point值的MultiPoint:
· MULTIPOINT(0 0, 20 20, 60 60)
· 具有2个LineString值的MultiLineString:
· MULTILINESTRING((10 10, 20 20), (15 15, 30 15))
· 具有2个Polygon值的MultiPolygon:
· MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0)),((5 5,7 5,7 7,5 7, 5 5)))
· 由2个Point值和1个LineString构成的GeometryCollection:
· GEOMETRYCOLLECTION(POINT(10 10), POINT(30 30), LINESTRING(15 15, 20 20))
在本章开始处给出的OGC规范文档中,可找到相应的Backus-Naur语法,它指定了用于编写WKT值的正式生产规则。
19.3.2. 著名的二进制(WKB)格式
WKB用于以二进制流的形式交换几何数据,二进制流由含几何WKB信息的BLOB值表示。
WKB使用1字节无符号整数、4字节无符号整数、以及8字节双精度数(IEEE 754格式)。1字节等于8比特。
例如,与POINT(1 1)对应的WKB值由下述21字节序列构成(在此,每个字节由2个十六进制数值表示):
0101000000000000000000F03F000000000000F03F
该序列可分为下述部分:
Byte order : 01
WKB type : 01000000
X : 000000000000F03F
Y : 000000000000F03F
表示如下:
· 字节顺序(Byte order)可以是0或1,分别表明little-endian或big-endian存储。little-endian和big-endian字节顺序也分别称为网络数据表示(NDR)和外部数据表示(XDR)。
· “WKB type”(WKB类型)是指明几何类型的代码。取值从1到7,分别表示Point、LineString、Polygon、MultiPoint、MultiLineString、MultiPolygon、和GeometryCollection。
· Point值具有X和Y坐标,每个值均用双精度值表示。
对于更复杂几何值的WKB值,它们是由更复杂的数据结构表示的,详情请参见OpenGIS规范。
19.4. 创建具备空间功能的MySQL数据库
· GEOMETRY
· POINT
· LINESTRING
· POLYGON
GEOMETRY能够保存任何类型的几何值。其他的单值类型POINT、LINESTRING以及POLYGON只能保存特定几何类型的值。
其他数据类型能保存多个值:
· MULTIPOINT
· MULTILINESTRING
· MULTIPOLYGON
· GEOMETRYCOLLECTION
GEOMETRYCOLLECTION能保存任意类型的对象集合。对于其他集合类型,MULTIPOINT、MULTILINESTRING、MULTIPOLYGON和GEOMETRYCOLLECTION,仅限于具有特定几何类型的集合成员。
19.4.2. 创建空间值
MySQL提供了众多以WKT表达式、以及可选的空间参考系ID(SRID)为输入参数的函数。它们将返回对应的几何对象。
GeomFromText()接受任何几何类型的WKT作为其第1个参量。在实施方案中也提供了与类型相关的构造函数,用于构造每一种几何类型的几何值。
-
GeomCollFromText(wkt[,srid]) , GeometryCollectionFromText(wkt[,srid])
使用其WKT表示和SRID构造GEOMETRYCOLLECTION值。
GeomFromText(wkt[,srid]) , GeometryFromText(wkt[,srid])
使用其WKT表示和SRID构造任何类型的几何值。
LineFromText(wkt[,srid]) , LineStringFromText(wkt[,srid])
使用其WKT表示和SRID构造LINESTRING值。
MLineFromText(wkt[,srid]) , MultiLineStringFromText(wkt[,srid])
使用其WKT表示和SRID构造MULTILINESTRING值。
MPointFromText(wkt[,srid]) , MultiPointFromText(wkt[,srid])
使用其WKT表示和SRID构造MULTIPOINT值。
MPolyFromText(wkt[,srid]) , MultiPolygonFromText(wkt[,srid])
使用其WKT表示和SRID构造MULTIPOLYGON值。
使用其WKT表示和SRID构造POINT值。
PolyFromText(wkt[,srid]) , PolygonFromText(wkt[,srid])
使用其WKT表示和SRID构造POLYGON值。
OpenGIS规范还介绍了用于构造Polygon或MultiPolygon值的可选函数,这些值基于环和封闭LineString值集合的WKT表达式。这些值可以相交。MySQL未实施下述函数:
MySQL提供了众多函数,它们将包含WKT表达式、或可选的空间参考系统ID(SRID)的BLOB作为输入参数。它们返回对应的几何对象。
GeomFromWKB()接受任何几何类型的WKB作为其第1个参量。在实施方案中也提供了与类型相关的构造函数,用于构造每一种几何类型的几何值。-
GeomCollFromWKB(wkb[,srid]) , GeometryCollectionFromWKB(wkb[,srid])
使用其WKB表示和SRID构造GEOMETRYCOLLECTION值。
GeomFromWKB(wkb[,srid]) , GeometryFromWKB(wkb[,srid])
使用其WKB表示和SRID构造任意类型的几何值。
LineFromWKB(wkb[,srid]) , LineStringFromWKB(wkb[,srid])
使用其WKB表示和SRID构造LINESTRING值。
MLineFromWKB(wkb[,srid]) , MultiLineStringFromWKB(wkb[,srid])
使用其WKB表示和SRID构造MULTILINESTRING值。
MPointFromWKB(wkb[,srid]) , MultiPointFromWKB(wkb[,srid])
使用其WKB表示和SRID构造MULTIPOINT值。
MPolyFromWKB(wkb[,srid]) , MultiPolygonFromWKB(wkb[,srid])
使用其WKB表示和SRID构造MULTIPOLYGON值。
使用其WKB表示和SRID构造POINT值。
PolyFromWKB(wkb[,srid]) , PolygonFromWKB(wkb[,srid])
使用其WKB表示和SRID构造POLYGON值。
OpenGIS规范还介绍了用于构造Polygon或MultiPolygon值的可选函数,这些值基于环和封闭LineString值集合的WKB表达式。这些值可以相交。MySQL未实施下述函数:
注释:MySQL未实施本节所列的函数。
MySQL为创建几何WKB表达式提供了有用的函数集合。本节介绍的函数是对OpenGIS规范的MySQL扩展。这些函数的结果是包含几何值(无SRID)的BLOB值。这些函数的结果可被GeomFromWKB()函数系列中任意函数的第1个参量取代。-
构造WKB GeometryCollection。如果任何参量不是构造良好的几何对象WKB表达式,返回值为NULL。
从多个WKB Point参量构造WKB LineString值。如果任何参量不是WKB Point,返回值为NULL。如果Point参量的数目小于2,返回值为NULL。
使用WKB LineString参量构造WKB MultiLineString值。如果任何参量不是WKB LineString,返回值为NULL。
使用WKB Point参量构造WKB MultiPoint值。如果任何参量不是WKB Point,返回值为NULL。
从一组WKB Polygon参量构造WKB MultiPolygon值。如果任何参量不是WKB Polygon,返回值为NULL。
使用其坐标构造WKB Point。
从多个WKB LineString参量构造WKB Polygon值。如果任何参量未表示为LinearRing的WKB形式(即,非封闭和简单LineString),返回值为NULL。
· 使用CREATE TABLE语句创建具有空间列的表:
· mysql> CREATE TABLE geom (g GEOMETRY);
· Query OK, 0 rows affected (0.02 sec)
· 使用ALTER TABLE语句在已有表中增加空间列,或将空间列从已有表中删除:
· mysql> ALTER TABLE geom ADD pt POINT;
· Query OK, 0 rows affected (0.00 sec)
· Records: 0 Duplicates: 0 Warnings: 0
· mysql> ALTER TABLE geom DROP pt;
· Query OK, 0 rows affected (0.00 sec)
· Records: 0 Duplicates: 0 Warnings: 0
19.4.4. 填充空间列
创建了空间列后,可用空间数据填充它们。
值应以内部几何格式保存,但你也能将其从WKT或WKB格式转换为内部几何格式。在下面的示例中,介绍了通过将WKT值转换为内部几何格式以便将几何值插入表中的方法。
你可以在INSERT语句中执行直接转换操作:
INSERT INTO geom VALUES (GeomFromText('POINT(1 1)'));
SET @g = 'POINT(1 1)';
INSERT INTO geom VALUES (GeomFromText(@g));
也可以在INSERT之前执行转换操作:
SET @g = GeomFromText('POINT(1 1)');
INSERT INTO geom VALUES (@g);
在下面的示例中,将多个复杂的几何值插入到了表中:
SET @g = 'LINESTRING(0 0,1 1,2 2)';
INSERT INTO geom VALUES (GeomFromText(@g));
SET @g = 'POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))';
INSERT INTO geom VALUES (GeomFromText(@g));
SET @g =
'GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(0 0,1 1,2 2,3 3,4 4))';
INSERT INTO geom VALUES (GeomFromText(@g));
在前面的所有示例中,均采用了GeomFromText()来创建几何值。你也可以使用与类型相关的函数:
SET @g = 'POINT(1 1)';
INSERT INTO geom VALUES (PointFromText(@g));
SET @g = 'LINESTRING(0 0,1 1,2 2)';
INSERT INTO geom VALUES (LineStringFromText(@g));
SET @g = 'POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))';
INSERT INTO geom VALUES (PolygonFromText(@g));
SET @g =
'GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(0 0,1 1,2 2,3 3,4 4))';
INSERT INTO geom VALUES (GeomCollFromText(@g));
注意,如果客户端应用程序打算使用几何值的WKB表示,它需要在队列中将正确构造的WKB发送至服务器。但是,存在数种满足该要求的方法。例如:
· 用十六进制文字语法插入POINT(1 1)值:
· mysql> INSERT INTO geom VALUES
· -> (GeomFromWKB(0x0101000000000000000000F03F000000000000F03F));
· ODBC应用程序能够发送WKB表达式,并使用具有BLOB类型的参量将其绑定到占位符:
· INSERT INTO geom VALUES (GeomFromWKB(?))
其他编程接口或许也支持类似的占位符机制。
在C程序中,可以使用mysql_real_escape_string()转义二进制值,并将结果包含在将发送至服务器的查询字符串。请参见25.2.3.52节,“mysql_real_escape_string()”MySQL支持下述用于在内部格式和WKT或WKB格式间转换几何值的函数:
将采用内部几何格式的值转换为其WKB表示,并返回二进制结果。
SELECT AsBinary(g) FROM geom;
将采用内部几何格式的值转换为其WKT表示,并返回字符串结果。
mysql> SET @g = 'LineString(1 1,2 2,3 3)'; mysql> SELECT AsText(GeomFromText(@g)); +--------------------------+ | AsText(GeomFromText(@g)) | +--------------------------+ | LINESTRING(1 1,2 2,3 3) | +--------------------------+
将字符串值从其WKT表示转换为内部几何格式,并返回结果。也支持多种与类型相关的函数,如PointFromText()和LineFromText(),请参见19.4.2.1节,“使用WKT函数创建Geometry(几何)值”。
将二进制值从其WKB表示转换为内部几何格式,并返回结果。也支持多种与类型相关的函数,如PointFromWKB()和LineFromWKB(),请参见19.4.2.2节,“使用WKB函数创建Geometry(几何)值”。
本节列出的函数不限制其参量,可接受任何类型的几何值。
返回几何值g的固有维数。结果可以是-1、0、1或2。(关于这些值的含义,请参见19.2.2节,“类Geometry”)。
mysql> SELECT Dimension(GeomFromText('LineString(1 1,2 2)')); +------------------------------------------------+ | Dimension(GeomFromText('LineString(1 1,2 2)')) | +------------------------------------------------+ | 1 | +------------------------------------------------+
-
返回几何值g的最小边界矩形(MBR)。结果以Polygon值的形式返回。
多边形(polygon)是由边界框的顶点定义的:POLYGON((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))
mysql> SELECT AsText(Envelope(GeomFromText('LineString(1 1,2 2)'))); +-------------------------------------------------------+ | AsText(Envelope(GeomFromText('LineString(1 1,2 2)'))) | +-------------------------------------------------------+ | POLYGON((1 1,2 1,2 2,1 2,1 1)) | +-------------------------------------------------------+
以字符串形式返回几何类型的名称,几何实例g是几何类型的成员。该名称与可实例化几何子类之一对应。
mysql> SELECT GeometryType(GeomFromText('POINT(1 1)')); +------------------------------------------+ | GeometryType(GeomFromText('POINT(1 1)')) | +------------------------------------------+ | POINT | +------------------------------------------+
返回指明了几何值g的空间参考系统ID的整数。
在MySQL中,SRID值仅是与几何值相关的整数。所有计算均是在欧几里得(平面)几何中进行的。
mysql> SELECT SRID(GeomFromText('LineString(1 1,2 2)',101)); +-----------------------------------------------+ | SRID(GeomFromText('LineString(1 1,2 2)',101)) | +-----------------------------------------------+ | 101 | +-----------------------------------------------+
OpenGIS规范还定义了下述函数,MySQL未实施这类函数:
Point由X和Y坐标构成,可使用下述函数获得它们:
以双精度数值返回点p的X坐标值。
mysql> SELECT X(GeomFromText('Point(56.7 53.34)')); +--------------------------------------+ | X(GeomFromText('Point(56.7 53.34)')) | +--------------------------------------+ | 56.7 | +--------------------------------------+
以双精度数值返回点p的Y坐标值。
mysql> SELECT Y(GeomFromText('Point(56.7 53.34)')); +--------------------------------------+ | Y(GeomFromText('Point(56.7 53.34)')) | +--------------------------------------+ | 53.34 | +--------------------------------------+
LineString由Point值组成。你可以提取LineString的特定点,计数它所包含的点数,或获取其长度。
返回LineString值1s的最后一个点的Point。
mysql> SET @ls = 'LineString(1 1,2 2,3 3)'; mysql> SELECT AsText(EndPoint(GeomFromText(@ls))); +-------------------------------------+ | AsText(EndPoint(GeomFromText(@ls))) | +-------------------------------------+ | POINT(3 3) | +-------------------------------------+
以双精度数值返回LineString值1s在相关的空间参考系中的长度。
mysql> SET @ls = 'LineString(1 1,2 2,3 3)'; mysql> SELECT GLength(GeomFromText(@ls)); +----------------------------+ | GLength(GeomFromText(@ls)) | +----------------------------+ | 2.8284271247462 | +----------------------------+
返回LineString值1s中的点数。
mysql> SET @ls = 'LineString(1 1,2 2,3 3)'; mysql> SELECT NumPoints(GeomFromText(@ls)); +------------------------------+ | NumPoints(GeomFromText(@ls)) | +------------------------------+ | 3 | +------------------------------+
返回LineString值1s中的第n个点。点编号从1开始。
mysql> SET @ls = 'LineString(1 1,2 2,3 3)'; mysql> SELECT AsText(PointN(GeomFromText(@ls),2)); +-------------------------------------+ | AsText(PointN(GeomFromText(@ls),2)) | +-------------------------------------+ | POINT(2 2) | +-------------------------------------+
返回LineString值1s的第一个点的Point。
mysql> SET @ls = 'LineString(1 1,2 2,3 3)'; mysql> SELECT AsText(StartPoint(GeomFromText(@ls))); +---------------------------------------+ | AsText(StartPoint(GeomFromText(@ls))) | +---------------------------------------+ | POINT(1 1) | +---------------------------------------+
OpenGIS规范还定义了下述函数,MySQL尚未实施这些函数:
以双精度数值形式返回MultiLineString值m1s的长度。mls的长度等于其元素的长度之和。
mysql> SET @mls = 'MultiLineString((1 1,2 2,3 3),(4 4,5 5))'; mysql> SELECT GLength(GeomFromText(@mls)); +-----------------------------+ | GLength(GeomFromText(@mls)) | +-----------------------------+ | 4.2426406871193 | +-----------------------------+
如果MultiLineString值m1s是封闭的(即StartPoint()和EndPoint()值对m1s中的每个LineString是相同的)返回1。如果mls是非封闭的,返回0,如果它是NULL,返回-1。
mysql> SET @mls = 'MultiLineString((1 1,2 2,3 3),(4 4,5 5))'; mysql> SELECT IsClosed(GeomFromText(@mls)); +------------------------------+ | IsClosed(GeomFromText(@mls)) | +------------------------------+ | 0 | +------------------------------+
以双精度数值形式返回Polygon值poly的面积,根据在其空间参考系中的测量值。
mysql> SET @poly = 'Polygon((0 0,0 3,3 0,0 0),(1 1,1 2,2 1,1 1))'; mysql> SELECT Area(GeomFromText(@poly)); +---------------------------+ | Area(GeomFromText(@poly)) | +---------------------------+ | 4 | +---------------------------+
以LineString形式返回Polygon值poly的外环。
mysql> SET @poly = -> 'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))'; mysql> SELECT AsText(ExteriorRing(GeomFromText(@poly))); +-------------------------------------------+ | AsText(ExteriorRing(GeomFromText(@poly))) | +-------------------------------------------+ | LINESTRING(0 0,0 3,3 3,3 0,0 0) | +-------------------------------------------+
以LineString形式返回Polygon值poly的第n个内环。环编号从1开始。
mysql> SET @poly = -> 'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))'; mysql> SELECT AsText(InteriorRingN(GeomFromText(@poly),1)); +----------------------------------------------+ | AsText(InteriorRingN(GeomFromText(@poly),1)) | +----------------------------------------------+ | LINESTRING(1 1,1 2,2 2,2 1,1 1) | +----------------------------------------------+
返回Polygon值poly的内环的数目。
mysql> SET @poly = -> 'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))'; mysql> SELECT NumInteriorRings(GeomFromText(@poly)); +---------------------------------------+ | NumInteriorRings(GeomFromText(@poly)) | +---------------------------------------+ | 1 | +---------------------------------------+
以双精度数值形式返回MultiPolygon值mpoly的面积,根据在其空间参考系中的测量结果。
mysql> SET @mpoly = -> 'MultiPolygon(((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1)))'; mysql> SELECT Area(GeomFromText(@mpoly)); +----------------------------+ | Area(GeomFromText(@mpoly)) | +----------------------------+ | 8 | +----------------------------+
OpenGIS规范还定义了下述函数,MySQL未实施这类函数:
返回GeometryCollection值gc中第n个几何对象。几何对象的编号从1开始。
mysql> SET @gc = 'GeometryCollection(Point(1 1),LineString(2 2, 3 3))'; mysql> SELECT AsText(GeometryN(GeomFromText(@gc),1)); +----------------------------------------+ | AsText(GeometryN(GeomFromText(@gc),1)) | +----------------------------------------+ | POINT(1 1) | +----------------------------------------+
返回GeometryCollection值gc中几何对象的数目。
mysql> SET @gc = 'GeometryCollection(Point(1 1),LineString(2 2, 3 3))'; mysql> SELECT NumGeometries(GeomFromText(@gc)); +----------------------------------+ | NumGeometries(GeomFromText(@gc)) | +----------------------------------+ | 2 | +----------------------------------+
在19.5.2节,“Geometry函数”中,我们讨论了一些可从已有几何对象构造新几何对象的函数:
Envelope(g)
StartPoint(ls)
EndPoint(ls)
PointN(ls,n)
ExteriorRing(poly)
InteriorRingN(poly,n)
GeometryN(gc,n)
OpenGIS建议了很多可生成几何对象的其他函数。它们是为实施空间操作符而设计的。
在MySQL中未实施这些函数。它们或许会在未来的版本中出现。
MySQL提供了一些可测试两个几何对象g1和g2最小边界矩形之间关系的函数。它们包括:
返回1或0以指明g1的最小边界矩形是否包含g2的最小边界矩形。
mysql> SET @g1 = GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0))'); mysql> SET @g2 = GeomFromText('Point(1 1)'); mysql> SELECT MBRContains(@g1,@g2), MBRContains(@g2,@g1); ----------------------+----------------------+ | MBRContains(@g1,@g2) | MBRContains(@g2,@g1) | +----------------------+----------------------+ | 1 | 0 | +----------------------+----------------------+
返回1或0以指明两个几何变量g1和g2的最小边界矩形是否不相交。
返回1或0以指明两个几何变量g1和g2的最小边界矩形是否相同。
返回1或0以指明两个几何变量g1和g2的最小边界矩形是否相交。
返回1或0以指明两个几何变量g1和g2的最小边界矩形是否交迭。
返回1或0以指明两个几何变量g1和g2的最小边界矩形是否接触。
返回1或0以指明g1的最小边界矩形是否位于g2的最小边界矩形内。
mysql> SET @g1 = GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0))'); mysql> SET @g2 = GeomFromText('Polygon((0 0,0 5,5 5,5 0,0 0))'); mysql> SELECT MBRWithin(@g1,@g2), MBRWithin(@g2,@g1); +--------------------+--------------------+ | MBRWithin(@g1,@g2) | MBRWithin(@g2,@g1) | +--------------------+--------------------+ | 1 | 0 | +--------------------+--------------------+
OpenGIS规范定义了下述函数。目前在MySQL尚未按照规范实施它们。对于那些已实施的函数,它们返回的结果与对应的基于MBR的函数返回的相同。包括下面列出的函数,但Distance()和Related()除外。
在未来的版本中,可能会实施这些函数,为空间分析提供全部支持,而不仅仅是基于MBR的支持。
这些函数作用在2个几何值g1和g2上。
返回1或0以指明g1是否完全包含g2。
-
如果g1在空间上与g2相交,返回1。如果g1为Polygon或MultiPolygon,返回NULL,或如果g2为Point或MultiPoint返回NULL。否则,返回0。
术语“空间上交叉”指的是2个给定几何对象之间的空间关系,它具有下述属性:
o 2个结合对象交叉。
o 其交叉结果将导致其维数小于两个给定几何对象最大维数的几何对象。
o 其交叉不等于两个几何对象中的任何1个。
返回1或0以指明g1是否与g2从空间上不相交。
以双精度数值形式返回2个几何对象中2点间的最短距离。
返回1或0以指明g1是否从空间上等同于g2。
返回1或0以指明g1是否从空间上与g2相交。
返回1或0以指明g1是否从空间上与g2交迭。如果2个几何对象交叉而且其交叉将导致具有相同维数但并不等同于任一几何对象的几何对象,将使用术语“空间交迭”。
返回1或0以指明由pattern_matrix指定的空间关系是否在g1和g2间存在。如果参量为NULL返回-1。模式矩形为字符串。如果实施了该函数,其规范将在此给出。
返回1或0以指明g1是否从空间上与g2接触。如果几何对象的内部不交叉,但1个几何对象的边界与另一个的边界或内部交叉,这两个几何对象是从空间上接触的。
返回1或0以指明g1是否从空间上位于g2内。
· 搜索包含给定点的所有对象的Point查询。
· 搜索与给定地区交迭的所有对象的地区查询。
MySQL采用了具有2次分裂特性的R-Trees来为空间列编制索引。使用几何对象的MBR来创建空间索引。对于大多数几何对象,MBR是包围几何对象的最小矩形。对于水平或垂直linestring,MBR退化为linestring的矩形。对于点,MBR是退化为点的矩形。
此外,还能在空间列上创建正常索引。需要为除POINT列之外的空间列上的任何索引(非空间)声明前缀。
19.6.1. 创建空间索引
MySQL能够使用与创建正规索引类似的语法创建空间索引,但使用了SPATIAL关键字进行了扩展。对于目前编制了索引的空间列,必须将其声明为NOT NULL。在下面的示例中,介绍了创建空间索引的方法。
· 对于CREATE TABLE:
· mysql> CREATE TABLE geom (g GEOMETRY NOT NULL, SPATIAL INDEX(g));
· 对于ALTER TABLE:
· mysql> ALTER TABLE geom ADD SPATIAL INDEX(g);
· 对于CREATE INDEX:
· mysql> CREATE SPATIAL INDEX sp_index ON geom (g);
对于MyISAM表,SPATIAL INDEX负责创建R-tree索引。对于支持空间索引的其他存储引擎,SPATIAL INDEX能够创建B-tree索引。对于准确的值查找而不是范围扫描,作用在空间值上的B-tree索引很有用。
要想撤销空间索引,可使用ALTER TABLE或DROP INDEX:
· 对于ALTER TABLE:
· mysql> ALTER TABLE geom DROP INDEX g;
· 对于DROP INDEX:
· mysql> DROP INDEX sp_index ON geom;
示例:假定表geom包含32000以上的几何对象,它们保存在类型为GEOMETRY的列g中。该表还有用于保存对象ID值的AUTO_INCREMENT列。
mysql> DESCRIBE geom; +-------+----------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+----------+------+-----+---------+----------------+ | fid | int(11) | | PRI | NULL | auto_increment | | g | geometry | | | | | +-------+----------+------+-----+---------+----------------+ 2 rows in set (0.00 sec) mysql> SELECT COUNT(*) FROM geom; +----------+ | count(*) | +----------+ | 32376 | +----------+ 1 row in set (0.00 sec)
要想在列g上添加空间索引,可使用下述语句:
mysql> ALTER TABLE geom ADD SPATIAL INDEX(g); Query OK, 32376 rows affected (4.05 sec) Records: 32376 Duplicates: 0 Warnings: 0
优化程序将调查可用的空间索引是否能包含在使用某些函数的查询搜索中,如WHERE子句中的MBRContains()或MBRWithin()函数。例如,假定我们打算找出位于给定矩形中的所有对象:
mysql> SELECT fid,AsText(g) FROM geom WHERE mysql> MBRContains(GeomFromText('Polygon((30000 15000,31000 15000,31000 16000,30000 16000,30000 15000))'),g); +-----+-----------------------------------------------------------------------------+ | fid | AsText(g) | +-----+-----------------------------------------------------------------------------+ | 21 | LINESTRING(30350.4 15828.8,30350.6 15845,30333.8 15845,30333.8 15828.8) | | 22 | LINESTRING(30350.6 15871.4,30350.6 15887.8,30334 15887.8,30334 15871.4) | | 23 | LINESTRING(30350.6 15914.2,30350.6 15930.4,30334 15930.4,30334 15914.2) | | 24 | LINESTRING(30290.2 15823,30290.2 15839.4,30273.4 15839.4,30273.4 15823) | | 25 | LINESTRING(30291.4 15866.2,30291.6 15882.4,30274.8 15882.4,30274.8 15866.2) | | 26 | LINESTRING(30291.6 15918.2,30291.6 15934.4,30275 15934.4,30275 15918.2) | | 249 | LINESTRING(30337.8 15938.6,30337.8 15946.8,30320.4 15946.8,30320.4 15938.4) | | 1 | LINESTRING(30250.4 15129.2,30248.8 15138.4,30238.2 15136.4,30240 15127.2) | | 2 | LINESTRING(30220.2 15122.8,30217.2 15137.8,30207.6 15136,30210.4 15121) | | 3 | LINESTRING(30179 15114.4,30176.6 15129.4,30167 15128,30169 15113) | | 4 | LINESTRING(30155.2 15121.4,30140.4 15118.6,30142 15109,30157 15111.6) | | 5 | LINESTRING(30192.4 15085,30177.6 15082.2,30179.2 15072.4,30194.2 15075.2) | | 6 | LINESTRING(30244 15087,30229 15086.2,30229.4 15076.4,30244.6 15077) | | 7 | LINESTRING(30200.6 15059.4,30185.6 15058.6,30186 15048.8,30201.2 15049.4) | | 10 | LINESTRING(30179.6 15017.8,30181 15002.8,30190.8 15003.6,30189.6 15019) | | 11 | LINESTRING(30154.2 15000.4,30168.6 15004.8,30166 15014.2,30151.2 15009.8) | | 13 | LINESTRING(30105 15065.8,30108.4 15050.8,30118 15053,30114.6 15067.8) | | 154 | LINESTRING(30276.2 15143.8,30261.4 15141,30263 15131.4,30278 15134) | | 155 | LINESTRING(30269.8 15084,30269.4 15093.4,30258.6 15093,30259 15083.4) | | 157 | LINESTRING(30128.2 15011,30113.2 15010.2,30113.6 15000.4,30128.8 15001) | +-----+-----------------------------------------------------------------------------+ 20 rows in set (0.00 sec)
我们使用EXPLAIN来检查该查询的执行方式(ID列已被删除,以便输出能更好地与页匹配):
mysql> EXPLAIN SELECT fid,AsText(g) FROM geom WHERE mysql> MBRContains(GeomFromText('Polygon((30000 15000,31000 15000,31000 16000,30000 16000,30000 15000))'),g); +-------------+-------+-------+---------------+------+---------+------+------+-------------+ | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +-------------+-------+-------+---------------+------+---------+------+------+-------------+ | SIMPLE | geom | range | g | g | 32 | NULL | 50 | Using where | +-------------+-------+-------+---------------+------+---------+------+------+-------------+ 1 row in set (0.00 sec)
让我们检查一下在没有空间索引的情况下会出现什么:
mysql> EXPLAIN SELECT fid,AsText(g) FROM g IGNORE INDEX (g) WHERE mysql> MBRContains(GeomFromText('Polygon((30000 15000,31000 15000,31000 16000,30000 16000,30000 15000))'),g); +-------------+-------+------+---------------+------+---------+------+-------+-------------+ | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +-------------+-------+------+---------------+------+---------+------+-------+-------------+ | SIMPLE | geom | ALL | NULL | NULL | NULL | NULL | 32376 | Using where | +-------------+-------+------+---------------+------+---------+------+-------+-------------+ 1 row in set (0.00 sec)
执行SELECT语句,忽略空间键:
mysql> SELECT fid,AsText(g) FROM geom IGNORE INDEX (g) WHERE mysql> MBRContains(GeomFromText('Polygon((30000 15000,31000 15000,31000 16000,30000 16000,30000 15000))'),g); +-----+-----------------------------------------------------------------------------+ | fid | AsText(g) | +-----+-----------------------------------------------------------------------------+ | 1 | LINESTRING(30250.4 15129.2,30248.8 15138.4,30238.2 15136.4,30240 15127.2) | | 2 | LINESTRING(30220.2 15122.8,30217.2 15137.8,30207.6 15136,30210.4 15121) | | 3 | LINESTRING(30179 15114.4,30176.6 15129.4,30167 15128,30169 15113) | | 4 | LINESTRING(30155.2 15121.4,30140.4 15118.6,30142 15109,30157 15111.6) | | 5 | LINESTRING(30192.4 15085,30177.6 15082.2,30179.2 15072.4,30194.2 15075.2) | | 6 | LINESTRING(30244 15087,30229 15086.2,30229.4 15076.4,30244.6 15077) | | 7 | LINESTRING(30200.6 15059.4,30185.6 15058.6,30186 15048.8,30201.2 15049.4) | | 10 | LINESTRING(30179.6 15017.8,30181 15002.8,30190.8 15003.6,30189.6 15019) | | 11 | LINESTRING(30154.2 15000.4,30168.6 15004.8,30166 15014.2,30151.2 15009.8) | | 13 | LINESTRING(30105 15065.8,30108.4 15050.8,30118 15053,30114.6 15067.8) | | 21 | LINESTRING(30350.4 15828.8,30350.6 15845,30333.8 15845,30333.8 15828.8) | | 22 | LINESTRING(30350.6 15871.4,30350.6 15887.8,30334 15887.8,30334 15871.4) | | 23 | LINESTRING(30350.6 15914.2,30350.6 15930.4,30334 15930.4,30334 15914.2) | | 24 | LINESTRING(30290.2 15823,30290.2 15839.4,30273.4 15839.4,30273.4 15823) | | 25 | LINESTRING(30291.4 15866.2,30291.6 15882.4,30274.8 15882.4,30274.8 15866.2) | | 26 | LINESTRING(30291.6 15918.2,30291.6 15934.4,30275 15934.4,30275 15918.2) | | 154 | LINESTRING(30276.2 15143.8,30261.4 15141,30263 15131.4,30278 15134) | | 155 | LINESTRING(30269.8 15084,30269.4 15093.4,30258.6 15093,30259 15083.4) | | 157 | LINESTRING(30128.2 15011,30113.2 15010.2,30113.6 15000.4,30128.8 15001) | | 249 | LINESTRING(30337.8 15938.6,30337.8 15946.8,30320.4 15946.8,30320.4 15938.4) | +-----+-----------------------------------------------------------------------------+ 20 rows in set (0.46 sec)
未使用索引时,该查询的执行时间将从0.00秒上升到0.46秒。
在未来的版本中,空间索引也可能会用于优化其他函数。请参见19.5.4节,“测试几何对象间空间关系的函数”。