最近學習了些MySQL geometry數據存儲和計算,在這裡記錄下。 1. 環境 geometry推薦在5.6版本以上使用,儘管大部分功能在5.5已經可用,除了距離計算函數st_distance等新增函數。 2. Geometry主要相關類 2.1 Geometry Geometry是所有此擴展中 ...
最近學習了些MySQL geometry數據存儲和計算,在這裡記錄下。
1. 環境
geometry推薦在5.6版本以上使用,儘管大部分功能在5.5已經可用,除了距離計算函數st_distance等新增函數。
2. Geometry主要相關類
2.1 Geometry
Geometry是所有此擴展中類型得基類,其他類型如Point,LineString,Polygon都是Geometry的子類。Geometry有一些屬性,這些屬性是所有其他幾何類的共有屬性:
type: 類型(Point, LineString,...)
SRID: 該值確定了用於描述定義幾何對象的坐標空間的空間坐標系統,參考鏈接:https://www.cnblogs.com/Joetao/articles/2086846.html
coordinates: 坐標值
interior, boundary, exterior: interior是幾何對象所展空間的部分,boundary是幾何對象的邊界,exterior是幾何對象未占有的空間。
MBR: 能夠覆蓋幾何對象的最小矩形,可以想象成信封,它由幾何對象中最大最小的坐標值組合而成:
((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))
simple/nonsimple: 幾何對象是否簡單
closed/not closed: 幾何對象是否封閉
dimension: 維度數(Point: 0, LineString: 1, Polygon: 2)
2.2 Point
顧名思義就是點,有一個坐標值,沒有長度、面積、邊界。
2.3 LineString
顧名思義就是線,由一系列點連接而成。
如果線從頭至尾沒有交叉,那就是簡單的(simple)
如果起點和終點重疊,那就是封閉的(closed)
2.4 Polygon
多邊形。可以是一個實心平面形,即沒有內部邊界,也可以有空洞,類似紐扣。
2.5 MultiPoint, MultiLineString, MultiPolygon, GeometryCollection
這4種類型都是集合類,是多個Point、LineString或Polygon組合在一起而成。
3. 幾何對象在MySQL中的數據格式
在MySQL中有3種表達幾何對象的格式:
-->WKT(文本格式)
-->WKB(二進位格式)
-->MySQL內部存儲格式
其中WKT格式簡單易讀,在這裡著重介紹:
3.1 WKT
3.1.1 Point
POINT(121.213342 31.234532)
經度(longitude)在前,維度(latitude)在後,用空格分隔
3.1.2 LineString
LINESTRING(121.342423 31.542423,121.345664 31.246790,121.453178 31.456862)
點與點之間用逗號分隔;一個點中的經緯度用空格分隔,與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))
由一個表示外部邊界的LineString和0個或多個表示內部邊界的LineString組成,最簡單的就是只有一個外邊界的情況: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. 幾何對象創建函數
MySQL表中的幾何對象有它自己的內部格式,我們需要將幾何對象從方便輸入的WKT格式轉換為其內部格式,才能進行進一步的存儲,計算等。
這裡主要講解使用WKT格式的函數,對於集合類對象的創建函數由於較少使用也不再列舉
GeomFromText(wkt): 創建一個任何類型的幾何對象Geometry
PointFromText(wkt): 創建一個Point對象
LineStringFromText(wkt): 創建一個LineString對象
PolygonFromText(wkt): 創建一個Polygon對象
5. 創建支持空間幾何對象的表
5.1 創建表
以下是我創建的一個樣例:
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就是存儲幾何對象的,類型為geometry,可以支持point,linestring,polygon等任意幾何對象。
引擎需要使用MyISAM。
表結構:
5.2 插入數據
5.2.1 插入點數據
INSERT INTO `t_geo_test` (ID,NAME,SHAPE) VALUES (1, 'P1', geomFromText('POINT(121.474103 31.232862)'));
5.2.2 插入線數據
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 插入多邊形數據
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 獲取數據
AsText(): 此函數能將幾何對象的內部存儲格式轉換為WKT格式
6. 常用函數
6.1 獲取幾何對象屬性的函數
6.1.1 Geometry
-->Dimension(g)
返回對象g的維數
-->Envelope(g)
返回對象g的最小邊界矩形(MBR)。結類型為Polygon值。
-->GeometryType(g)
以字元串形式返回幾何類型的名稱,如POINT,LINESTRING
-->IsClosed(g)
返回對象g是否封閉
-->IsSimple(g)
返回對象g是否簡單
6.1.2 Point
-->X(p)
以雙精度數值返回點p的X坐標值(經度)。
-->Y(p)
以雙精度數值返回點p的Y坐標值(緯度)。
6.1.3 LineString
-->EndPoint(line)
返回對象line的最後一個點Point
-->StartPoint(line)
返回對象line的第一個點Point
-->PointN(line, N)
返回對象line中第N個點,N從1開始
6.1.4 Polygon
-->ExteriorRing(poly)
返回對象poly的外環,類型為LineString
-->InteriorRingN(poly, N)
返回對象poly的第N個內環,N從1開始
-->NumInteriorRings(poly)
返回對象poly的neihuan個數
6.2 從現成幾何對象創建新的對象
6.2.1 st_union(g1, g2)
將g1和g2合併為一個集合類對象
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);
結果:
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)
返回幾何對象,該對象表示了幾何值g1與g2的點集合差異
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);
結果:
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)
返回幾何對象,該對象表示了幾何值g1與g2的點集合交集
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);
結果:
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 幾何對象之間空間關係的函數
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的反函數
6.3.4 st_within(g1, g2)
g1在g2內則返回1,否則返回0
7. 空間索引
對錶中的geometry類型的欄位進行索引可以優化搜索,MySQL中通過對Geometry對象的MBR創建索引
創建:
CREATE SPATIAL INDEX i_shape ON `t_geo_test`(SHAPE);
刪除:
DROP INDEX i_shape ON `t_geo_test`;
8.一些註意事項
8.1 目前MySQL中支持的空間坐標系統沒有gcj02,bd09等國內坐標系,預設使用WGS84地球坐標系,所以在創建幾何對象時輸入的坐標值儘量使用WGS84坐標,以避免誤差。
8.2 MySQL中的計算距離,長度,面積等絕對數值的空間計算函數(area(), GLength(), st_distance())存在一定的誤差,儘量不要使用。