目录
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çš�OpenGIS®简单特征规èŒ�,在该文档中,提出了扩展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的边界总为空ã€�
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的边界中ã€�
几何对象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值的正式生产规则ã€�
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规范ã€�
· GEOMETRY
· POINT
· LINESTRING
· POLYGON
GEOMETRY能够保存任何类型的几何值。其他的单值类åž�POINTã€�LINESTRING以及POLYGON只能保存特定几何类型çš�值ã€�
其他数据类型能保存多个值:
· MULTIPOINT
· MULTILINESTRING
· MULTIPOLYGON
· GEOMETRYCOLLECTION
GEOMETRYCOLLECTION能保存任意类型的对象集合。对于其他集合类型,MULTIPOINTã€�MULTILINESTRINGã€�MULTIPOLYGONå’�GEOMETRYCOLLECTION,仅限于具有特定几何类型的集合成员ã€�
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
创建了空间列后,可用空间数据填充它们ã€�
值应以内部几何格式保存,但你也能将其ä»�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中未实施这些函数。它们或许会在未来的版本中出现ã€�
返回几何对象,该对象代表所有距几何å€�g的距离小于或等于d的所有点ã€�
返回几何对象,该对象代表几何å€�g的凸包ã€�
返回几何对象,该对象表示了几何å€�g1ä¸�g2的点集合差异ã€�
返回几何对象,该对象表示了几何å€�g1ä¸�g2的点集合交集ã€�
返回几何对象,该对象表示了几何å€�g1ä¸�g2的点集合对称差ã€�
返回几何对象,该对象表示了几何å€�g1ä¸�g2的点集合联合ã€�
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列之外的空间列上的任何索引(非空间)声明前缀ã€�
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节,“测试几何对象间空间关系的函数â€�ã€�
这是MySQL参考手册的翻译版本,关于MySQL参考手册,请访é—�dev.mysql.com。原始参考手册为英文版,与英文版参考手册相比,本翻译版可能不是最新的ã€�