跳到主要内容

空间数据格式

seekdb 支持两种标准的空间数据格式用于表示查询中的几何对象:

  • Well-Know Text Format(WKT)

  • Well-Know Binary Format(WKB)

WKT

WKT 是基于EBNF(Extended Backus Naur Form)定义的。WKT 既可以作为数据格式(本文中称作 WKT-Data),也可以在 GIS 用于 SRS 的定义(在本文中简称 WKT-SRS)。

Point

Point 不使用逗号分隔。格式示例如下:

POINT(15 20)

如下示例使用 ST_X() 从 Point 对象中提取 X 坐标。 第一个直接使用 Point() 函数生成对象。第二个使用通过 ST_GeomFromText() 转换为 Point 的 WKT 表示。

obclient> SELECT ST_X(Point(15, 20));
+---------------------+
| ST_X(Point(15, 20)) |
+---------------------+
| 15 |
+---------------------+
1 row in set

obclient> SELECT ST_X(ST_GeomFromText('POINT(15 20)'));
+---------------------------------------+
| ST_X(ST_GeomFromText('POINT(15 20)')) |
+---------------------------------------+
| 15 |
+---------------------------------------+
1 row in set

Line

Line 是由多个点组成,点之间使用逗号隔开。格式示例如下:

LINESTRING(0 0, 10 10, 20 25, 50 60)

Polygon

Polygon 是由至少一条外环(闭合的线)以及若干条(可以是 0 条)内环(闭合的线)组成。格式示例如下:

POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))

MultiPoint

MultiPoint 由多个点组成,和线比较类似,但是语义不同。多点连接组成线,多点离散是 MultiPoint。格式示例如下:

MULTIPOINT(0 0, 20 20, 60 60)

在函数 ST_MPointFromText() 以及 ST_GeoFromText() 中,MultiPoint 中的点采用括号括起来也是合法的。格式示例如下:

ST_MPointFromText('MULTIPOINT (1 1, 2 2, 3 3)')
ST_MPointFromText('MULTIPOINT ((1 1), (2 2), (3 3))')

MultiLineString

MultiLineString 是多条线的集合。格式示例如下:

MULTILINESTRING((10 10, 20 20), (15 15, 30 15))

MultiPolygon

MultiPolygon 是多个多边形的集合。格式示例如下:

MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0)),((5 5,7 5,7 7,5 7, 5 5)))

GeometryCollection

GeometryCollection 可以是多种基础类型以及集合类型的集合。

GEOMETRYCOLLECTION(POINT(10 10), POINT(30 30), LINESTRING(15 15, 20 20))

WKB

WKB 是基于 OpenGIS 规范开发的,支持 7 种类型(Point、Linestring、Polygon、Multipoint、Multilinestring、Multipolygon 和 Geometrycollection)以及对应格式定义。

Point

POINT(1 -1) 为例,格式定义如下表所示。

组件名称规格类型取值
Byte order1 byteunsigned int01
WKB type4 bytesunsigned int01000000
X coordinate8 bytesdouble-precision000000000000F03F
Y coordinate8 bytesdouble-precision000000000000F0BF

Linestring

基于 LINESTRING(1 -1, -1 1) 举例,格式定义如下表所示。Num points 要求大于等于 2。

组件名称规格类型取值
Byte order1 byteunsigned int01
WKB type4 bytesunsigned int02000000
Num points4 bytesunsigned int02000000
X coordinate8 bytesdouble-precision000000000000F03F
Y coordinate8 bytesdouble-precision000000000000F0BF
X coordinate8 bytesdouble-precision000000000000F0BF
Y coordinate8 bytesdouble-precision000000000000F03F

Polygon

组件名称规格类型取值
Byte order1 byteunsigned int01
WKB type4 bytesunsigned int03000000
Num rings4 bytesunsigned int大于等于 1
repeat ring---

MultiPoint

组件名称规格类型取值
Byte order1 byteunsigned int01
WKB type4 bytesunsigned int04000000
Num points4 bytesunsigned int要求 Num points >= 1
repeat POINT---

MultilineString

组件名称规格类型取值
Byte order1 byteunsigned int01
WKB type4 bytesunsigned int05000000
Num linestrings4 bytesunsigned int大于等于 1
repeat LINESTRING---

MultiPolygon

组件名称规格类型取值
Byte order1 byteunsigned int01
WKB type4 bytesunsigned int06000000
Num polygons4 bytesunsigned int大于等于 1
repeat POLYGON---

GeometryCollection

组件名称规格类型取值
Byte order1 byteunsigned int01
WKB type4 bytesunsigned int07000000
Num wkbs4 bytesunsigned int-
repeat WKB---

说明:

  • 只有 GeometryCollection 可以为空,表示存储了 0 个元素,其它类型都不能为空。
  • LENGTH() 作用在 GIS 对象上的时候,返回的是存储的二进制的长度。
obclient [test]> SET @g = ST_GeomFromText('POINT(1 -1)');
Query OK, 0 rows affected

obclient [test]> SELECT LENGTH(@g);
+------------+
| LENGTH(@g) |
+------------+
| 25 |
+------------+
1 row in set

obclient [test]> SELECT HEX(@g);
+----------------------------------------------------+
| HEX(@g) |
+----------------------------------------------------+
| 000000000101000000000000000000F03F000000000000F0BF |
+----------------------------------------------------+
1 row in set

句法和几何合法性

句法合法性

句法合法需要满足如下条件:

  • Linestring 需要至少 2 个点
  • Polygon 需要至少一个环
  • Polygon 是需要闭环的(首位的 2 个点相同)
  • Polygon 的环至少需要 4 个点(最小的多边形是三角形,第一个点和最后一个点相同)
  • 除了 GeometryCollection,其它的集合类型都不能为空

几何合法性

几何合法需要满足如下条件:

  • Polygon 不能自己和自己相交
  • Polygon 的外环要在内环外面
  • Multipolygons 中不能存在重叠的多边形

通过 ST_IsValid() 函数可以显式检查几何对象的几何合法性。

GIS 示例

插入示例

//转换函数和 WKT 都放在 SQL 语句内
INSERT INTO geom VALUES (ST_GeomFromText('POINT(1 1)'));

//WKT 放在参数中
SET @g = 'POINT(1 1)';
INSERT INTO geom VALUES (ST_GeomFromText(@g));

//转换表达式直接放在参数中
SET @g = ST_GeomFromText('POINT(1 1)');
INSERT INTO geom VALUES (@g);

//使用统一的转换函数
SET @g = 'LINESTRING(0 0,1 1,2 2)';
INSERT INTO geom VALUES (ST_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 (ST_GeomFromText(@g));

SET @g ='GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(0 0,1 1,2 2,3 3,4 4))';
INSERT INTO geom VALUES (ST_GeomFromText(@g));

//使用基于类型的转换函数
SET @g = 'POINT(1 1)';
INSERT INTO geom VALUES (ST_PointFromText(@g));

SET @g = 'LINESTRING(0 0,1 1,2 2)';
INSERT INTO geom VALUES (ST_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 (ST_PolygonFromText(@g));

SET @g =
'GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(0 0,1 1,2 2,3 3,4 4))';
INSERT INTO geom VALUES (ST_GeomCollFromText(@g));

//也可以直接基于 WKB 进行插入
INSERT INTO geom VALUES(ST_GeomFromWKB(X'0101000000000000000000F03F000000000000F03F'));

查询示例

//查询并转换成 WKT 输出
SELECT ST_AsText(g) FROM geom;

//查询并转换为 WKB 输出
SELECT ST_AsBinary(g) FROM geom;