最近學(xué)習(xí)了些MySQL geometry數(shù)據(jù)存儲(chǔ)和計(jì)算矛紫,在這里記錄下桩皿。
1. 環(huán)境
geometry推薦在5.6版本以上使用,盡管大部分功能在5.5已經(jīng)可用手销,除了距離計(jì)算函數(shù)st_distance等新增函數(shù)苫幢。
2. Geometry主要相關(guān)類
2.1 Geometry
Geometry是所有此擴(kuò)展中類型得基類,其他類型如Point,LineString,Polygon都是Geometry的子類垫挨。Geometry有一些屬性韩肝,這些屬性是所有其他幾何類的共有屬性:
type: 類型(Point, LineString,...)
SRID:?該值確定了用于描述定義幾何對(duì)象的坐標(biāo)空間的空間坐標(biāo)系統(tǒng),參考鏈接:https://www.cnblogs.com/Joetao/articles/2086846.html
coordinates: 坐標(biāo)值
interior,?boundary,?exterior: interior是幾何對(duì)象所展空間的部分九榔,boundary是幾何對(duì)象的邊界哀峻,exterior是幾何對(duì)象未占有的空間。
MBR: 能夠覆蓋幾何對(duì)象的最小矩形哲泊,可以想象成信封剩蟀,它由幾何對(duì)象中最大最小的坐標(biāo)值組合而成:
((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))
simple/nonsimple: 幾何對(duì)象是否簡(jiǎn)單
closed/not closed: 幾何對(duì)象是否封閉
dimension: 維度數(shù)(Point: 0, LineString: 1, Polygon: 2)
2.2 Point
顧名思義就是點(diǎn),有一個(gè)坐標(biāo)值切威,沒(méi)有長(zhǎng)度育特、面積、邊界先朦。
2.3 LineString
顧名思義就是線缰冤,由一系列點(diǎn)連接而成。
如果線從頭至尾沒(méi)有交叉喳魏,那就是簡(jiǎn)單的(simple)
如果起點(diǎn)和終點(diǎn)重疊棉浸,那就是封閉的(closed)
2.4 Polygon
多邊形〈滩剩可以是一個(gè)實(shí)心平面形迷郑,即沒(méi)有內(nèi)部邊界枝恋,也可以有空洞,類似紐扣嗡害。
2.5 MultiPoint, MultiLineString, MultiPolygon, GeometryCollection
這4種類型都是集合類焚碌,是多個(gè)Point、LineString或Polygon組合在一起而成就漾。
3. 幾何對(duì)象在MySQL中的數(shù)據(jù)格式
在MySQL中有3種表達(dá)幾何對(duì)象的格式:
-->WKT(文本格式)
-->WKB(二進(jìn)制格式)
-->MySQL內(nèi)部存儲(chǔ)格式
其中WKT格式簡(jiǎn)單易讀呐能,在這里著重介紹:
3.1 WKT
3.1.1 Point
POINT(121.213342 31.234532)
經(jīng)度(longitude)在前,維度(latitude)在后抑堡,用空格分隔
3.1.2 LineString
LINESTRING(121.342423 31.542423,121.345664 31.246790,121.453178 31.456862)
點(diǎn)與點(diǎn)之間用逗號(hào)分隔摆出;一個(gè)點(diǎn)中的經(jīng)緯度用空格分隔,與POINT格式一致
3.1.3 Polygon
POLYGON((121.342423 31.542423,121.345664 31.246790,121.453178 31.456862),(121.563633 31.566652,121.233565 31.234565,121.568756 31.454367))
由一個(gè)表示外部邊界的LineString和0個(gè)或多個(gè)表示內(nèi)部邊界的LineString組成首妖,最簡(jiǎn)單的就是只有一個(gè)外邊界的情況:POLYGON((0 0,10,0 10 10, 0 10))
3.1.4 集合類格式
MULTIPOINT(0 0, 20 20, 60 60)
MULTILINESTRING((10 10, 20 20), (15 15, 30 15))
MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0)),((5 5,7 5,7 7,5 7, 5 5)))
GEOMETRYCOLLECTION(POINT(10 10), POINT(30 30), LINESTRING(15 15, 20 20))
4. 幾何對(duì)象創(chuàng)建函數(shù)
MySQL表中的幾何對(duì)象有它自己的內(nèi)部格式偎漫,我們需要將幾何對(duì)象從方便輸入的WKT格式轉(zhuǎn)換為其內(nèi)部格式,才能進(jìn)行進(jìn)一步的存儲(chǔ)有缆,計(jì)算等象踊。
這里主要講解使用WKT格式的函數(shù),對(duì)于集合類對(duì)象的創(chuàng)建函數(shù)由于較少使用也不再列舉
GeomFromText(wkt): 創(chuàng)建一個(gè)任何類型的幾何對(duì)象Geometry
PointFromText(wkt): 創(chuàng)建一個(gè)Point對(duì)象
LineStringFromText(wkt): 創(chuàng)建一個(gè)LineString對(duì)象
PolygonFromText(wkt): 創(chuàng)建一個(gè)Polygon對(duì)象
5. 創(chuàng)建支持空間幾何對(duì)象的表
5.1 創(chuàng)建表
以下是我創(chuàng)建的一個(gè)樣例:
CREATE TABLE `t_geo_test` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`NAME` varchar(64) NOT NULL,
`SHAPE` geometry NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=MyISAM AUTO_INCREMENT=10 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC
這里的字段SHAPE就是存儲(chǔ)幾何對(duì)象的棚壁,類型為geometry杯矩,可以支持point,linestring,polygon等任意幾何對(duì)象。
引擎需要使用MyISAM袖外。
表結(jié)構(gòu):
5.2 插入數(shù)據(jù)
5.2.1 插入點(diǎn)數(shù)據(jù)
INSERT INTO `t_geo_test` (ID,NAME,SHAPE) VALUES (1, 'P1', geomFromText('POINT(121.474103 31.232862)'));
5.2.2 插入線數(shù)據(jù)
INSERT INTO `t_geo_test` (ID,NAME,SHAPE) VALUES (2, 'L1', geomFromText('LINESTRING(121.474103 31.232862,121.472462 31.231339,121.471984 31.232821)'));
5.2.3 插入多邊形數(shù)據(jù)
INSERT INTO `t_geo_test` (ID,NAME,SHAPE) VALUES (5, 'POLYGON_1', geomfromtext('POLYGON((121.474243 31.234504, 121.471775 31.233348, 121.470724 31.23155, 121.471603 31.230229, 121.472655 31.230357, 121.475777 31.232045, 121.474243 31.234504))'));
5.3 獲取數(shù)據(jù)
AsText(): 此函數(shù)能將幾何對(duì)象的內(nèi)部存儲(chǔ)格式轉(zhuǎn)換為WKT格式
6. 常用函數(shù)
6.1 獲取幾何對(duì)象屬性的函數(shù)
6.1.1 Geometry
-->Dimension(g)
返回對(duì)象g的維數(shù)
-->Envelope(g)
返回對(duì)象g的最小邊界矩形(MBR)史隆。結(jié)類型為Polygon值。
-->GeometryType(g)
以字符串形式返回幾何類型的名稱曼验,如POINT,LINESTRING
-->IsClosed(g)
返回對(duì)象g是否封閉
-->IsSimple(g)
返回對(duì)象g是否簡(jiǎn)單
6.1.2 Point
-->X(p)
以雙精度數(shù)值返回點(diǎn)p的X坐標(biāo)值(經(jīng)度)泌射。
-->Y(p)
以雙精度數(shù)值返回點(diǎn)p的Y坐標(biāo)值(緯度)。
6.1.3?LineString
-->EndPoint(line)
返回對(duì)象line的最后一個(gè)點(diǎn)Point
-->StartPoint(line)
返回對(duì)象line的第一個(gè)點(diǎn)Point
-->PointN(line, N)
返回對(duì)象line中第N個(gè)點(diǎn)鬓照,N從1開(kāi)始
6.1.4 Polygon
-->ExteriorRing(poly)
返回對(duì)象poly的外環(huán)熔酷,類型為L(zhǎng)ineString
-->InteriorRingN(poly, N)
返回對(duì)象poly的第N個(gè)內(nèi)環(huán),N從1開(kāi)始
-->NumInteriorRings(poly)
返回對(duì)象poly的neihuan個(gè)數(shù)
6.2 從現(xiàn)成幾何對(duì)象創(chuàng)建新的對(duì)象
6.2.1 st_union(g1, g2)
將g1和g2合并為一個(gè)集合類對(duì)象
SET @g1 = geomFromText('POLYGON((121.474243 31.234504,121.471775 31.233348,121.470724 31.23155,121.471603 31.230229,121.472655 31.230357,121.475777 31.232045,121.474243 31.234504))');
SET @g2 = geomFromText('POLYGON((121.474243 31.234804,121.471775 31.233948,121.471724 31.23155,121.471903 31.230229,121.472655 31.230157,121.475777 31.231045,121.474243 31.234804))');
SELECT st_union(@g1, @g2);
結(jié)果:
POLYGON((121.472655 31.230157, 121.471903 31.230229, 121.471898134093 31.2302649098516, 121.471603 31.230229, 121.470724 31.23155, 121.471761757556 31.2333253454665, 121.471775 31.233948, 121.474243 31.234804, 121.474597 31.2339365384615, 121.475777 31.232045, 121.475442678789 31.2318642395248, 121.475777 31.231045, 121.472655 31.230157))
6.2.2 st_difference(g1, g2)
返回幾何對(duì)象豺裆,該對(duì)象表示了幾何值g1與g2的點(diǎn)集合差異
SET @g1 = geomFromText('POLYGON((121.474243 31.234504,121.471775 31.233348,121.470724 31.23155,121.471603 31.230229,121.472655 31.230357,121.475777 31.232045,121.474243 31.234504))');
SET @g2 = geomFromText('POLYGON((121.474243 31.234804,121.471775 31.233948,121.471724 31.23155,121.471903 31.230229,121.472655 31.230157,121.475777 31.231045,121.474243 31.234804))');
SELECT st_difference(@g1,@g2);
結(jié)果:
MULTIPOLYGON(((121.471603 31.230229, 121.470724 31.23155, 121.471761757556 31.2333253454665, 121.471724 31.23155, 121.471898134093 31.2302649098516, 121.471603 31.230229)), ((121.475442678789 31.2318642395248, 121.474597 31.2339365384615, 121.475777 31.232045, 121.475442678789 31.2318642395248)))
6.2.3?st_intersection(g1,g2)
返回幾何對(duì)象拒秘,該對(duì)象表示了幾何值g1與g2的點(diǎn)集合交集
SET @g1 = geomFromText('POLYGON((121.474243 31.234504,121.471775 31.233348,121.470724 31.23155,121.471603 31.230229,121.472655 31.230357,121.475777 31.232045,121.474243 31.234504))');
SET @g2 = geomFromText('POLYGON((121.474243 31.234804,121.471775 31.233948,121.471724 31.23155,121.471903 31.230229,121.472655 31.230157,121.475777 31.231045,121.474243 31.234804))');
SELECT st_intersection(@g1,@g2);
結(jié)果:
POLYGON((121.471898134093 31.2302649098516, 121.471724 31.23155, 121.471761757556 31.2333253454665, 121.471775 31.233348, 121.474243 31.234504, 121.474597 31.2339365384615, 121.475442678789 31.2318642395248, 121.472655 31.230357, 121.471898134093 31.2302649098516))
6.3 幾何對(duì)象之間空間關(guān)系的函數(shù)
6.3.1 st_contains(g1, g2)
返回1: g1完全包含g2;返回0: g1未包含g2
6.3.2 st_crosses(g1, g2),?st_intersects(g1, g2)
返回1: g1與g2相交留储;返回0:g1與g2未相交
6.3.3 st_disjoint(g1, g2)
是st_crosses的反函數(shù)
6.3.4 st_within(g1, g2)
g1在g2內(nèi)則返回1翼抠,否則返回0
7. 空間索引
對(duì)表中的geometry類型的字段進(jìn)行索引可以優(yōu)化搜索,MySQL中通過(guò)對(duì)Geometry對(duì)象的MBR創(chuàng)建索引
創(chuàng)建:
CREATE SPATIAL INDEX i_shape ON `t_geo_test`(SHAPE);
刪除:
DROP INDEX?i_shape ON?`t_geo_test`;
8.一些注意事項(xiàng)
8.1 目前MySQL中支持的空間坐標(biāo)系統(tǒng)沒(méi)有g(shù)cj02,bd09等國(guó)內(nèi)坐標(biāo)系获讳,默認(rèn)使用WGS84地球坐標(biāo)系阴颖,所以在創(chuàng)建幾何對(duì)象時(shí)輸入的坐標(biāo)值盡量使用WGS84坐標(biāo),以避免誤差丐膝。
8.2 MySQL中的計(jì)算距離量愧,長(zhǎng)度钾菊,面積等絕對(duì)數(shù)值的空間計(jì)算函數(shù)(area(), GLength(), st_distance())存在一定的誤差,盡量不要使用偎肃。