OceanBase V4.2特性解析:MySQL模式下GIS空间表达式的场景及能力解析
1. 背景
1.1. OceanBase Mysql gis空间表达式的应用场景及能力
在OceanBase 4.1版本中,mysql模式下支持了gis数据类型以及部分空间对象相关的表达式,随着客户使用空间数据的需求日益增长,需要快速地补齐空间数据存储和计算分析的能力;
针对mysql的空间表达式的能力,目前补齐了部分gis表达式,包括:
- 空间关系计算表达式:判断空间关系是否成立(ST_Crosses/ST_Overlaps)
- 空间对象计算表达式:根据输入的空间对象计算出新的空间对象(ST_Difference/ST_Union/ST_SymDifference)
- 空间对象测量表达式:测量空间对象长度(ST_Length)
- 空间对象分析表达式:计算空间对象质心点(ST_Centroid)
- 空间对象格式转换表达式:空间对象转换为json类型(ST_AsGeoJSON)
pg作为gis行业使用最广的数据库,提供了部分空间表达式的功能是mysql不具备的,且该部分表达式也被广泛应用,同时pg还支持3维空间对象存储。因此ob在兼容mysql gis的能力基础上也对空间表达式的能力进行了扩展补充,作为ob mysql模式下特有的空间表达式(这部分空间表达式以'_'做为前缀);包括以下几类:
-
- 空间关系计算表达式:判断空间关系是否成立(_ST_Touches/_ST_Equals)
- 空间对象构造表达式:构造空间对象(_ST_MakeEnvelope/)
- 空间对象计算表达式:根据输入的空间对象计算出新的空间对象(_ST_ClipByBox2D)
- 空间对象属性访问表达式:查询空间对象某一属性(_ST_GeometryType/_ST_IsCollection/_ST_NumInteriorRings)
- 空间对象分析表达式:计算一个保证位于几何体内部的点(_ST_PointOnSurface)
- 空间对象格式转换表达式:空间对象转换为mapbox vector tile格式(ST_AsMVTGeom/_ST_AsMVT)
ob mysql gis也支持了3维空间对象的存储能力。
1.2 OceanBase v4.2.2,Mysql gis空间表达式的特性支持
OceanBase 4.2.2版本下新增的兼容mysql gis空间表达式如下:
表达式名称 | 功能介绍 |
boolean ST_Crosses(geometry g1, geometry g2) | 判断两个Geometry g1和g2在空间上是否有交叉,即几何体内部有部分点相同,但不完全相同 |
boolean ST_Overlaps(geometry g1, geometry g2) | 判断两个几何体是否空间上相交且具有相同的维度,但并不完全互相包含。 |
geometry ST_Difference(geometry g1, geometry g2) | 返回geometry g1中不和geometry g2相交的部分,等价于g1 - ST_Intersection(g1, g2) |
geometry ST_Union(geometry g1, geometry g2) | 返回geometry g1和geometry g2的并集 |
geometry ST_Length(geometry g1, unit string) | 计算LineString类型或MultiLinestring类型的长度,该长度和线段所在空间坐标系有关,MultiLinestring类型的长度等于其包含的LineString长度之和;unit参数指定了长度显示单位 |
geometry ST_SymDifference(geometry geomA, geometry geomB) | 返回geometry A和Geometry B不重叠的部分,等价于ST_Difference(ST_Union(g1, g2), ST_Intersection(g1, g2))。 |
ST_AsGeoJSON(g [, max_dec_digits [, options]]) | 将geometry转换为对应的json格式,包含两个可选参数max_dec_digits和flag。 |
ST_Centroid(geometry A) | 计算几何体的质心点,该质心点不保证在几何体上 |
此外,新增ob mysql特有gis空间表达式如下:
表达式名称 | 功能介绍 |
geometry _ST_PointOnSurface(geometry g1) | 返回一个保证位于几何体内部的点,和ST_Centroid不同,ST_Centroid返回的中心点不一定在几何体上 |
geometry _ST_MakeEnvelope(float xmin, float ymin, float xmax, float ymax, integer srid=unknown); | 该函数通过输入左下角坐标与右上角坐标,构造一个矩形; |
geometry _ST_ClipByBox2D(geometry geom, box2d box); | 通过Box快速剪裁几何体,不会检查输入几何体的合法性,也不保证输出的几何体是合法的。该函数第二个参数虽然是Box,但实际上可以输入任意Geometry,会隐式转换为Box |
text _ST_GeometryType(geometry g1); | 返回Geometry的类型 |
boolean _ST_IsCollection(geometry g1); | 判断输入的Geometry是否为集合类型 |
integer _ST_NumInteriorRings(geometry a_polygon); | 返回Polygon的内环数,如果Geometry非Polygon类型,则返回NULL |
boolean _ST_Touches(geometry A, geometry B) | 判断两个Geometry A和B边界是否至少有一个共同点,且内部不相交。注意若两个Geometry均为Point类型,直接返回false,因为Point没有边界 |
boolean ST_Equals(geometry A, geometry B); | 判断两个Geometry A和B是否在空间结构上相等,即包含相同的点集,但不考虑点集顺序是否一致 |
bytea _ST_AsMVT(table_name.*, text name, integer extent, text geom_name, text feature_id_name); | 将一组行聚合返回一个使用Google Protocol Buffers编码格式二进制的mapbox矢量瓦片,blob类型;第一个参数是必须的,后面的参数可选 |
geometry _ST_MakeValid(geometry input); | 尝试将输入的无效的多边形修复为一个有效的多边形 |
geometry ST_AsMVTGeom(geometry geom, // 输入空间对象 box2d bounds, // MVT空间坐标范围 integer extent=4096, // 矢量切片的范围(4096个单位) integer buffer=256, // 缓存区大小 boolean clip_geom=true); | 将一个输入的空间对象转换到bounds定义的map vector tile空间坐标系下,超出bounds的部分且位于buffer指定的缓冲区以内的部分根据clip_geom参数的配置来决定是否裁剪;map vector tile空间坐标系起始点位于左上角(屏幕参考系);转换后输出的满足mapbox vector tile 规范的有效geometry,常作为st_asmvt的入参。 |
支持3维gis数据存储,gis表达式适配3维数据分类如下:
- 输入WKT/WKB格式数据构造空间对象的表达式,支持输入3维数据构造空间对象;
- 将存储的空间数据转换成指定格式WKT/WKB/EWKB/EWKT输出的表达式,支持查询3维空间数据;
- 不支持输入3D数据;
类型 | 表达式 | 功能 | 适配内容 |
构造空间对象 | st_geomfromtext | 输入wkt格式创建几何值 | 如果是3d geo,跳过检查经纬度范围的逻辑;封装geo_to_wkb,增加3d-wkb格式转成swkb; |
st_geometryfromtext | 输入wkt格式创建几何值 | ||
_st_geomfromewkt | 输入ewkt格式创建几何值 | 同上 | |
_st_geogfromtext | 输入wkt格式创建几何值,默认geography坐标系 | 同上 | |
_st_geographyfromtext | 输入wkt格式创建几何值,默认geography坐标系 | ||
st_geomfromwkb | 输入wkb格式创建几何值 | 增加校验3d wkb格式是否合法 | |
st_geometryfromwkb | 输入wkb格式创建几何值 | ||
_st_geomfromewkb | 输入ewkb格式创建几何值 | 3d-ewkb和iso 3d-wkb的type表示的方式不一样,需要做转换同样需要校验输入的wkb是否合法 | |
格式转换 | st_astext/st_aswkt | 输出wkt格式 | 读取swkb转换成geo对象,然后转换成3d-wkt格式。 |
st_aswkb/st_asbinary | 输出wkb格式 | swkb转wkb | |
_st_asewkb | 输出ewkb格式 | ewkb转wkb | |
_st_asewkt | 输出ewkt格式 | wkt前面需要加上"srid=xxx" | |
空间计算表达式 | st_area | 计算空间对象面积 | 将3维空间数据转为2维处理 |
st_intersects | 计算两个空间对象是否相交 | ||
st_transform | 将一个空间对象的坐标转换到指定的空间坐标系下 | ||
_st_covers | 计算空间对象A是否包含空间对象B | ||
st_buffer | 计算一个距离小于或等于给定距离的所有点的POLYGON/MULTIPOLYGON | ||
st_distance | 计算两个空间对象间距离 | ||
_st_dwithin | 计算空间对象A是否在一定距离内被包含于空间对象B | ||
st_distance_sphere | 返回球体上两个点和/或多点之间的最小球面距离 | ||
st_contains | 计算空间对象A是否包含空间对象B | ||
st_within | 计算空间对象A是否包含于空间对象B | ||
ST_Crosses | 判断两个Geometry g1和g2在空间上是否有交叉,即几何体内部有部分点相同,但不完全相同 | ||
ST_Overlaps | 判断两个几何体是否空间上相交且具有相同的维度,但并不完全互相包含。 | ||
_ST_Touches | 判断两个Geometry A和B边界是否至少有一个共同点,且内部不相交。注意若两个Geometry均为Point类型,直接返回false,因为Point没有边界 | ||
ST_Equals | 判断两个Geometry A和B是否在空间结构上相等,即包含相同的点集,但不考虑点集顺序是否一致 |
- 以下表达式支持空间索引
表达式名称 | 功能介绍 |
boolean ST_Crosses(geometry g1, geometry g2) | 判断两个Geometry g1和g2在空间上是否有交叉,即几何体内部有部分点相同,但不完全相同 |
boolean ST_Overlaps(geometry g1, geometry g2) | 判断两个几何体是否空间上相交且具有相同的维度,但并不完全互相包含。 |
boolean _ST_Touches(geometry A, geometry B) | 判断两个Geometry A和B边界是否至少有一个共同点,且内部不相交。注意若两个Geometry均为Point类型,直接返回false,因为Point没有边界 |
boolean ST_Equals(geometry A, geometry B); | 判断两个Geometry A和B是否在空间结构上相等,即包含相同的点集,但不考虑点集顺序是否一致 |
2. 使用操作
2.1. ST_Crosses(g1,g2)
支持空间索引,判断两个Geometry g1和g2在空间上是否有交叉,即几何体内部有部分点相同,但不完全相同。
OceanBase(root@oceanbase)>select st_crosses(st_geomfromtext('LINESTRING(1 1, 11 11)'), st_geomfromtext('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'));
+------------------------------------------------------------------------------------------------------------------+
| st_crosses(st_geomfromtext('LINESTRING(1 1, 11 11)'), st_geomfromtext('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))')) |
+------------------------------------------------------------------------------------------------------------------+
| 1 |
+------------------------------------------------------------------------------------------------------------------+
1 row in set (0.004 sec)
2.2. ST_Overlaps(g1,g2)
支持空间索引,判断两个几何体是否空间上相交且具有相同的维度,但并不完全互相包含。
OceanBase(root@oceanbase)>SELECT ST_OVERLAPS(ST_GEOMFROMTEXT('POLYGON((0 0,0 10,10 10,10 0,0 0,0 0),(2 2,2 4,4 4,4 2,2 2))'), ST_GEOMFROMTEXT('POLYGON((0 0,0 5,5 5,5 0,0 0))'));
+-------------------------------------------------------------------------------------------------------------------------------------------------+
| ST_OVERLAPS(ST_GEOMFROMTEXT('POLYGON((0 0,0 10,10 10,10 0,0 0,0 0),(2 2,2 4,4 4,4 2,2 2))'), ST_GEOMFROMTEXT('POLYGON((0 0,0 5,5 5,5 0,0 0))')) |
+-------------------------------------------------------------------------------------------------------------------------------------------------+
| 1 |
+-------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.005 sec)
2.3. ST_Difference(g1,g2)
返回geometry A中不和geometry B相交的部分,等价于A - ST_Intersection(A, B)
。
OceanBase(root@oceanbase)>SELECT ST_AsText(ST_Difference(ST_GeomFromText('LINESTRING(50 100, 50 200)'),ST_GeomFromText('LINESTRING(50 50, 50 150)')));
+----------------------------------------------------------------------------------------------------------------------+
| ST_AsText(ST_Difference(ST_GeomFromText('LINESTRING(50 100, 50 200)'),ST_GeomFromText('LINESTRING(50 50, 50 150)'))) |
+----------------------------------------------------------------------------------------------------------------------+
| LINESTRING(50 150,50 200) |
+----------------------------------------------------------------------------------------------------------------------+
1 row in set (0.004 sec)
2.4. ST_Union(g1,g2)
返回geometry A和geometry B的并集
OceanBase(root@oceanbase)>SELECT ST_AsText(ST_Union(ST_GeomFromText('LINESTRING(50 100, 50 200)'),ST_GeomFromText('LINESTRING(50 50, 50 150)')));
+-----------------------------------------------------------------------------------------------------------------+
| ST_AsText(ST_Union(ST_GeomFromText('LINESTRING(50 100, 50 200)'),ST_GeomFromText('LINESTRING(50 50, 50 150)'))) |
+-----------------------------------------------------------------------------------------------------------------+
| MULTILINESTRING((50 100,50 200),(50 50,50 100)) |
+-----------------------------------------------------------------------------------------------------------------+
1 row in set (0.004 sec)
2.5. ST_Length(ls[,unit])
unit参数指定了长度显示单位,默认为metre(米),常见的有foot、centimetre等。全部单位和其对应转换系数如下,当且仅当srid != 0且单位合法时生效。
+--------------------------------------+---------------------+
| UNIT_NAME | CONVERSION_FACTOR |
+--------------------------------------+---------------------+
| British chain (Benoit 1895 A) | 20.1167824 |
| British chain (Benoit 1895 B) | 20.116782494375872 |
| British chain (Sears 1922 truncated) | 20.116756 |
| British chain (Sears 1922) | 20.116765121552632 |
| British foot (1865) | 0.30480083333333335 |
| British foot (1936) | 0.3048007491 |
| British foot (Benoit 1895 A) | 0.3047997333333333 |
| British foot (Benoit 1895 B) | 0.30479973476327077 |
| British foot (Sears 1922 truncated) | 0.30479933333333337 |
| British foot (Sears 1922) | 0.3047994715386762 |
| British link (Benoit 1895 A) | 0.201167824 |
| British link (Benoit 1895 B) | 0.2011678249437587 |
| British link (Sears 1922 truncated) | 0.20116756 |
| British link (Sears 1922) | 0.2011676512155263 |
| British yard (Benoit 1895 A) | 0.9143992 |
| British yard (Benoit 1895 B) | 0.9143992042898124 |
| British yard (Sears 1922 truncated) | 0.914398 |
| British yard (Sears 1922) | 0.9143984146160288 |
| centimetre | 0.01 |
| chain | 20.1168 |
| Clarke's chain | 20.1166195164 |
| Clarke's foot | 0.3047972654 |
| Clarke's link | 0.201166195164 |
| Clarke's yard | 0.9143917962 |
| fathom | 1.8288 |
| foot | 0.3048 |
| German legal metre | 1.0000135965 |
| Gold Coast foot | 0.3047997101815088 |
| Indian foot | 0.30479951024814694 |
| Indian foot (1937) | 0.30479841 |
| Indian foot (1962) | 0.3047996 |
| Indian foot (1975) | 0.3047995 |
| Indian yard | 0.9143985307444408 |
| Indian yard (1937) | 0.91439523 |
| Indian yard (1962) | 0.9143988 |
| Indian yard (1975) | 0.9143985 |
| kilometre | 1000 |
| link | 0.201168 |
| metre | 1 |
| millimetre | 0.001 |
| nautical mile | 1852 |
| Statute mile | 1609.344 |
| US survey chain | 20.11684023368047 |
| US survey foot | 0.30480060960121924 |
| US survey link | 0.2011684023368047 |
| US survey mile | 1609.3472186944375 |
| yard | 0.9144 |
+--------------------------------------+---------------------+
OceanBase(root@oceanbase)>SET @ls = ST_GeomFromText('LineString(1 1,2 2,3 3)', 4326);
Query OK, 0 rows affected (0.001 sec)OceanBase(root@oceanbase)>SELECT ST_Length(@ls, "foot");
+------------------------+
| ST_Length(@ls, "foot") |
+------------------------+
| 1029205.9131247795 |
+------------------------+
1 row in set (0.001 sec)OceanBase(root@oceanbase)>SELECT ST_Length(@ls);
+-------------------+
| ST_Length(@ls) |
+-------------------+
| 313701.9623204328 |
+-------------------+
1 row in set (0.004 sec)
2.6. _ST_PointOnSurface
定义:geometry _st_pointonsurface(a geometry)
,返回geometry类型为POINT。
返回一个保证位于几何体内部的点,和ST_Centroid
不同,ST_Centroid
返回的中心点不一定在几何体上。例如下图绿色点为中心点,红色点为ST_PointOnSurface
所返回的内部点。
棕色:中心点,绿色:内部点
OceanBase(root@oceanbase)>SELECT ST_AsText(_ST_PointOnSurface(geom)) AS pt_on_surf,-> ST_AsText(ST_Centroid(geom)) AS centroid-> FROM (SELECT ST_GeomFromText('POLYGON ((0 0, 0 10, 10 10, 10 8, 2 8, 2 2, 10 2, 10 0, 0 0))') AS geom) AS t;
+------------+----------------------------+
| pt_on_surf | centroid |
+------------+----------------------------+
| POINT(1 5) | POINT(4.076923076923077 5) |
+------------+----------------------------+
1 row in set (0.001 sec)
2.7. _ST_MakeEnvelope
该函数通过输入左下角坐标与右上角坐标,构造一个矩形,常作为以Box为参数的其他函数的输入
-- 定义
geometry _ST_MakeEnvelope(float xmin, float ymin, float xmax, float ymax, integer srid=unknown);-- 构造矩形
OceanBase(root@oceanbase)>SELECT ST_AsText( _ST_MakeEnvelope(10, 10, 11, 11, 4326) );
+-----------------------------------------------------+
| ST_AsText( _ST_MakeEnvelope(10, 10, 11, 11, 4326) ) |
+-----------------------------------------------------+
| POLYGON((10 10,11 10,11 11,10 11,10 10)) |
+-----------------------------------------------------+
1 row in set (0.004 sec)-- 作为其他函数的输入
-- Rely on implicit cast from geometry to box2d for the second parameter
OceanBase(root@oceanbase)>SELECT ST_ASTEXT(_ST_ClipByBox2D(ST_GEOMFROMTEXT('POLYGON((-2 -2, -2 11, 11 11, 11 -2, -2 -2))'), -> _ST_MakeEnvelope(0,0,10,10)));
+-------------------------------------------------------------------------------------------------------------------------------------------------+
| ST_ASTEXT(_ST_ClipByBox2D(ST_GEOMFROMTEXT('POLYGON((-2 -2, -2 11, 11 11, 11 -2, -2 -2))'), _ST_MakeEnvelope(0,0,10,10))) |
+-------------------------------------------------------------------------------------------------------------------------------------------------+
| POLYGON((0 0,0 10,10 10,10 0,0 0)) |
+-------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.005 sec)
2.8. _ST_ClipByBox2D
geometry _ST_ClipByBox2D(geometry geom, box2d box);
通过Box快速剪裁几何体,不会检查输入几何体的合法性,也不保证输出的几何体是合法的。
该函数第二个参数虽然是Box,但实际上可以输入任意Geometry,会转换为对应的Box。
OceanBase(root@oceanbase)>SELECT ST_ASTEXT(_ST_ClipByBox2D(ST_GEOMFROMTEXT('POLYGON((-2 -2, -2 11, 11 11, 11 -2, -2 -2))'), -> _ST_MakeEnvelope(0,0,10,10)));
+-------------------------------------------------------------------------------------------------------------------------------------------------+
| ST_ASTEXT(_ST_ClipByBox2D(ST_GEOMFROMTEXT('POLYGON((-2 -2, -2 11, 11 11, 11 -2, -2 -2))'), _ST_MakeEnvelope(0,0,10,10))) |
+-------------------------------------------------------------------------------------------------------------------------------------------------+
| POLYGON((0 0,0 10,10 10,10 0,0 0)) |
+-------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.005 sec)
2.9. _ST_GeometryType
返回Geometry的SQL-MM类型,格式为ST_[TYPE]
OceanBase(root@oceanbase)>SELECT _ST_GeometryType(ST_GeomFromText('LINESTRING(77.29 29.07,77.42 29.26,77.27 29.31,77.29 29.07)'));
+--------------------------------------------------------------------------------------------------+
| _ST_GeometryType(ST_GeomFromText('LINESTRING(77.29 29.07,77.42 29.26,77.27 29.31,77.29 29.07)')) |
+--------------------------------------------------------------------------------------------------+
| ST_LineString |
+--------------------------------------------------------------------------------------------------+
1 row in set (0.001 sec)
2.10. _ST_IsCollection
判断输入的Geometry是否为集合类型,包括
- GEOMETRYCOLLECTION
- MULTI{POINT,POLYGON,LINESTRING,CURVE,SURFACE}
- COMPOUNDCURVE,OB暂不支持,报错处理
OceanBase(root@oceanbase)> SELECT _ST_IsCollection(st_geomfromtext('LINESTRING(0 0, 1 1)'));
+-----------------------------------------------------------+
| _ST_IsCollection(st_geomfromtext('LINESTRING(0 0, 1 1)')) |
+-----------------------------------------------------------+
| 0 |
+-----------------------------------------------------------+
1 row in set (0.003 sec)
2.11. _ST_NumInteriorRings
返回Polygon的内环数,如果Geometry非Polygon类型,则返回NULL
-- 定义
integer _ST_NumInteriorRings(geometry a_polygon);-- 示例
OceanBase(root@oceanbase)>select _ST_NumInteriorRings(ST_GeomFromText('POLYGON((2 2 1,2 8 5,8 8 7,8 2 4,2 2 1))'));
+-----------------------------------------------------------------------------------+
| _ST_NumInteriorRings(ST_GeomFromText('POLYGON((2 2 1,2 8 5,8 8 7,8 2 4,2 2 1))')) |
+-----------------------------------------------------------------------------------+
| 0 |
+-----------------------------------------------------------------------------------+
1 row in set (0.003 sec)
2.12. _ST_Touches
支持空间索引,判断两个Geometry A和B边界是否至少有一个共同点,且内部不相交。注意若两个Geometry均为Point类型,直接返回false,因为Point没有边界。
OceanBase(root@oceanbase)>SELECT _ST_Touches(st_geomfromtext('LINESTRING(0 0, 1 1, 0 2)'),-> st_geomfromtext('POINT(0 2)'));
+-------------------------------------------------------------------------------------------------------------+
| _ST_Touches(st_geomfromtext('LINESTRING(0 0, 1 1, 0 2)'),st_geomfromtext('POINT(0 2)')) |
+-------------------------------------------------------------------------------------------------------------+
| 1 |
+-------------------------------------------------------------------------------------------------------------+
1 row in set (0.003 sec)
2.13. ST_Equals
支持空间索引,判断两个Geometry A和B是否在空间结构上相等,即包含相同的点集,但不考虑点集顺序是否一致。
OceanBase(root@oceanbase)>SELECT ST_Equals(ST_GeomFromText('LINESTRING(0 0, 10 10)'),-> ST_GeomFromText('LINESTRING(0 0, 5 5, 10 10)'));
+-------------------------------------------------------------------------------------------------------+
| ST_Equals(ST_GeomFromText('LINESTRING(0 0, 10 10)'),
ST_GeomFromText('LINESTRING(0 0, 5 5, 10 10)')) |
+-------------------------------------------------------------------------------------------------------+
| 1 |
+-------------------------------------------------------------------------------------------------------+
1 row in set (0.003 sec)
2.14. _ST_AsMVT
功能:将表包含gis列的所有行数据聚合返回一个使用Google Protocol Buffers编码格式二进制的mapbox矢量瓦片;
OceanBase(root@oceanbase)>SELECT 'TG1', hex(_ST_AsMVT(q.*, 'test', 4096, 'geom')) FROM (SELECT 1 AS c1, ST_GeomFromText('POINT(25 17)')AS geom) AS q;
+-----+----------------------------------------------------------------------+
| TG1 | hex(_ST_AsMVT(q.*, 'test', 4096, 'geom')) |
+-----+----------------------------------------------------------------------+
| TG1 | 1A200A0474657374120B12020000180122030932221A026331220228012880207802 |
+-----+----------------------------------------------------------------------+
1 row in set (0.004 sec)
上例中_ST_AsMVT中生成的结果中编码了字段C1和它的值(1)、字段geom和它的值('POINT(25 17)')点的信息;
参数说明:
- row:聚合的一组行,表名.*
- name:layer的命名,默认为"default"
- extent:瓦片的范围(默认4096个单位, 4096 * 4096),直接透传保存在layer中;
- geom_name:通过该参数指定行中geom列,默认取第一个geom列;如果一行中有多个gis列,未被指定的gis列直接当成string进行编码;
- feature_id_name: 通过该参数指定行中的列,将该列中的值作为feature的id;如果不指定,feature id默认为0;
输出的pb编码的二进制数据可读性不高,为提高可测试性,提高脚本来解析:mvt_debug.js
// 执行脚本,将表达式结果作为参数传入
node mvt_debug.js '1A200A0474657374120B12020000180122030932221A026331220228012880207802'
// 解析结果
layer name: [ 'test' ]
feature count: 1
feature VectorTileFeature {properties: { c1: 1 },extent: 4096,type: 1,_pbf: {buf: Uint8Array(34) [26, 32, 10, 4, 116, 101, 115, 116, 18,11, 18, 2, 0, 0, 24, 1, 34, 3,9, 50, 34, 26, 2, 99, 49, 34, 2,40, 1, 40, 128, 32, 120, 2],pos: 21,type: 2,length: 34},_geometry: 17,_keys: [ 'c1' ],_values: [ 1 ]
}
id undefined
bbox [ 25, 17, 25, 17 ]
GEO [ [ { x: 25, y: 17 } ] ]
2.15. _ST_MakeValid
将输入的无效多边形修复为有效的多边形,只支持投影坐标系,不支持地理坐标系
OceanBase(root@oceanbase)>select st_astext(_st_makevalid(st_geomfromtext('POLYGON((0 0,1 1,2 2,0 2,1 1,2 0,0 0))')));
+-------------------------------------------------------------------------------------+
| st_astext(_st_makevalid(st_geomfromtext('POLYGON((0 0,1 1,2 2,0 2,1 1,2 0,0 0))'))) |
+-------------------------------------------------------------------------------------+
| MULTIPOLYGON(((1 1,2 2,0 2,1 1)),((1 1,0 0,2 0,1 1))) |
+-------------------------------------------------------------------------------------+
1 row in set (0.006 sec)
上例中将自相交的多边形,
转换为2个三角形
2.16. ST_SymDifference(g1,g2)
OceanBase(root@oceanbase)>SET @g1 = ST_GeomFromText('MULTIPOINT(5 0,15 10,15 25)');
Query OK, 0 rows affected (0.001 sec)OceanBase(root@oceanbase)>SET @g2 = ST_GeomFromText('MULTIPOINT(1 1,15 10,15 25)');
Query OK, 0 rows affected (0.001 sec)OceanBase(root@oceanbase)>SELECT ST_AsText(ST_SymDifference(@g1, @g2));
+---------------------------------------+
| ST_AsText(ST_SymDifference(@g1, @g2)) |
+---------------------------------------+
| MULTIPOINT((1 1),(5 0)) |
+---------------------------------------+
1 row in set (0.004 sec)
2.17. ST_AsGeoJSON(g[,max_dec_digits[,options]])
--flag 0(000)到7(111)表现
OceanBase(root@oceanbase)>SELECT ST_AsGeoJSON(ST_GeomFromText('POINT(11.11111 12.22222)', 4326),1,0);
+---------------------------------------------------------------------+
| ST_AsGeoJSON(ST_GeomFromText('POINT(11.11111 12.22222)', 4326),1,0) |
+---------------------------------------------------------------------+
| {"type": "Point", "coordinates": [12.2, 11.1]} |
+---------------------------------------------------------------------+
1 row in set (0.003 sec)OceanBase(root@oceanbase)>SELECT ST_AsGeoJSON(ST_GeomFromText('POINT(11.11111 12.22222)', 4326),1,1);
+----------------------------------------------------------------------------------+
| ST_AsGeoJSON(ST_GeomFromText('POINT(11.11111 12.22222)', 4326),1,1) |
+----------------------------------------------------------------------------------+
| {"bbox": [12.2, 11.1, 12.2, 11.1], "type": "Point", "coordinates": [12.2, 11.1]} |
+----------------------------------------------------------------------------------+
1 row in set (0.001 sec)OceanBase(root@oceanbase)>SELECT ST_AsGeoJSON(ST_GeomFromText('POINT(11.11111 12.22222)', 4326),1,2);
+--------------------------------------------------------------------------------------------------------------+
| ST_AsGeoJSON(ST_GeomFromText('POINT(11.11111 12.22222)', 4326),1,2) |
+--------------------------------------------------------------------------------------------------------------+
| {"crs": {"type": "name", "properties": {"name": "EPSG:4326"}}, "type": "Point", "coordinates": [12.2, 11.1]} |
+--------------------------------------------------------------------------------------------------------------+
1 row in set (0.001 sec)OceanBase(root@oceanbase)>SELECT ST_AsGeoJSON(ST_GeomFromText('POINT(11.11111 12.22222)', 4326),1,3);
+------------------------------------------------------------------------------------------------------------------------------------------------+
| ST_AsGeoJSON(ST_GeomFromText('POINT(11.11111 12.22222)', 4326),1,3) |
+------------------------------------------------------------------------------------------------------------------------------------------------+
| {"crs": {"type": "name", "properties": {"name": "EPSG:4326"}}, "bbox": [12.2, 11.1, 12.2, 11.1], "type": "Point", "coordinates": [12.2, 11.1]} |
+------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.001 sec)OceanBase(root@oceanbase)>SELECT ST_AsGeoJSON(ST_GeomFromText('POINT(11.11111 12.22222)', 4326),1,4);
+-------------------------------------------------------------------------------------------------------------------------------+
| ST_AsGeoJSON(ST_GeomFromText('POINT(11.11111 12.22222)', 4326),1,4) |
+-------------------------------------------------------------------------------------------------------------------------------+
| {"crs": {"type": "name", "properties": {"name": "urn:ogc:def:crs:EPSG::4326"}}, "type": "Point", "coordinates": [12.2, 11.1]} |
+-------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.001 sec)OceanBase(root@oceanbase)>SELECT ST_AsGeoJSON(ST_GeomFromText('POINT(11.11111 12.22222)', 4326),1,5);
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ST_AsGeoJSON(ST_GeomFromText('POINT(11.11111 12.22222)', 4326),1,5) |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
| {"crs": {"type": "name", "properties": {"name": "urn:ogc:def:crs:EPSG::4326"}}, "bbox": [12.2, 11.1, 12.2, 11.1], "type": "Point", "coordinates": [12.2, 11.1]} |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.001 sec)OceanBase(root@oceanbase)>SELECT ST_AsGeoJSON(ST_GeomFromText('POINT(11.11111 12.22222)', 4326),1,6);
+-------------------------------------------------------------------------------------------------------------------------------+
| ST_AsGeoJSON(ST_GeomFromText('POINT(11.11111 12.22222)', 4326),1,6) |
+-------------------------------------------------------------------------------------------------------------------------------+
| {"crs": {"type": "name", "properties": {"name": "urn:ogc:def:crs:EPSG::4326"}}, "type": "Point", "coordinates": [12.2, 11.1]} |
+-------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.001 sec)OceanBase(root@oceanbase)>SELECT ST_AsGeoJSON(ST_GeomFromText('POINT(11.11111 12.22222)', 4326),1,7);
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ST_AsGeoJSON(ST_GeomFromText('POINT(11.11111 12.22222)', 4326),1,7) |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
| {"crs": {"type": "name", "properties": {"name": "urn:ogc:def:crs:EPSG::4326"}}, "bbox": [12.2, 11.1, 12.2, 11.1], "type": "Point", "coordinates": [12.2, 11.1]} |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.001 sec)
2.18. ST_Centroid
OceanBase(root@oceanbase)>SELECT ST_AsText(_ST_PointOnSurface(geom)) AS pt_on_surf,-> ST_AsText(ST_Centroid(geom)) AS centroid-> FROM (SELECT ST_GeomFromText('POLYGON ((0 0, 0 10, 10 10, 10 8, 2 8, 2 2, 10 2, 10 0, 0 0))') AS geom) AS t;
+------------+----------------------------+
| pt_on_surf | centroid |
+------------+----------------------------+
| POINT(1 5) | POINT(4.076923076923077 5) |
+------------+----------------------------+
1 row in set (0.001 sec)
2.19. _ST_AsMVTGeom
OceanBase(root@oceanbase)>SELECT ST_AsText(_ST_AsMVTGeom(ST_GeomFromText('POLYGON ((0 0, 0 -5, 10 0, 10 5, 0 0))'),ST_GeomFromText('POLYGON((0 0,0 4096,4096 4096,4096 0,0 0))'),4096, 0, false));
+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ST_AsText(_ST_AsMVTGeom(ST_GeomFromText('POLYGON ((0 0, 0 -5, 10 0, 10 5, 0 0))'),ST_GeomFromText('POLYGON((0 0,0 4096,4096 4096,4096 0,0 0))'),4096, 0, false)) |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| POLYGON((0 4096,10 4091,10 4096,0 4101,0 4096)) |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.002 sec)OceanBase(root@oceanbase)>SELECT ST_AsText(_ST_AsMVTGeom(ST_GeomFromText('POLYGON ((0 0, 0 -5, 10 0, 10 5, 0 0))'),ST_GeomFromText('POLYGON((0 0,0 4096,4096 4096,4096 0,0 0))'),4096, 0, true));
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ST_AsText(_ST_AsMVTGeom(ST_GeomFromText('POLYGON ((0 0, 0 -5, 10 0, 10 5, 0 0))'),ST_GeomFromText('POLYGON((0 0,0 4096,4096 4096,4096 0,0 0))'),4096, 0, true)) |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
| POLYGON((0 4096,10 4091,10 4096,0 4096)) |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.001 sec)
2.20. 3维空间对象
3维空间对象ddl/dml与2维基本一致,只是3维空间对象无法写入到由子类型定义的字段上
# 创建gis字段
OceanBase(root@oceanbase)>create table geo_3d(g geometry);
Query OK, 0 rows affected (0.302 sec)# 写入3维的点
OceanBase(root@oceanbase)>insert into geo_3d values(ST_GeomFromText('POINT Z (0 0 0)'));
Query OK, 1 row affected (0.025 sec)#查询3维数据
OceanBase(root@oceanbase)>select st_aswkt(g) from geo_3d;
+-----------------+
| st_aswkt(g) |
+-----------------+
| POINT Z (0 0 0) |
+-----------------+
1 row in set (0.007 sec)# 对3维空间对象做空间计算时,会先转换为2维;
# 如下例所示point(0 0 0)和point(0 0 1)在3维空间下是不相交的,转换到2维就是相交的
OceanBase(root@oceanbase)>select st_intersects(g, st_geomfromtext('POINT Z (0 0 1)')) from geo_3d;
+------------------------------------------------------+
| st_intersects(g, st_geomfromtext('POINT Z (0 0 1)')) |
+------------------------------------------------------+
| 1 |
+------------------------------------------------------+
1 row in set (0.005 sec)# 部分表达式不支持3维数据
OceanBase(root@oceanbase)>select st_x(g,1) from geo_3d;
ERROR 3037 (22023): Invalid GIS data provided to function st_x.# 用子类型(point/linestring等)定义gis字段,不支持插入3维数据
OceanBase(root@oceanbase)>create table t(geo point);
Query OK, 0 rows affected (0.511 sec)
# 可以写入2维数据
OceanBase(root@oceanbase)>insert into t values(ST_GeomFromText('POINT(0 0)'));
Query OK, 1 row affected (0.004 sec)
# 无法写入3维数据
OceanBase(root@oceanbase)>insert into t values(ST_GeomFromText('POINT Z (0 0 0)'));
ERROR 1416 (22003): Cannot get geometry object from data you send to the GEOMETRY field.
3. 总结和展望
如上所述,本次特性为满足用户的需求,补充了部分ob mysql特有的gis空间表达式;同时补齐了部分兼容mysql gis的空间表达式。目前ob mysql gis提供的空间计算和分析的能力与mysql gis仍然有一定差距,将在后续的版本迭代中快速补齐相关功能。
相关文章:

OceanBase V4.2特性解析:MySQL模式下GIS空间表达式的场景及能力解析
1. 背景 1.1. OceanBase Mysql gis空间表达式的应用场景及能力 在OceanBase 4.1版本中,mysql模式下支持了gis数据类型以及部分空间对象相关的表达式,随着客户使用空间数据的需求日益增长,需要快速地补齐空间数据存储和计算分析的能力&#…...

HSL模型和HSB模型,和懒人配色的Color Hunt
色彩不仅仅是视觉上的享受,它在数据可视化中也扮演着关键角色。通过合理运用色彩模型,我们可以使数据更具可读性和解释性。在这篇文章将探讨HSL(Hue, Saturation, Lightness)和HSB(Hue, Saturation, Brightness&#x…...

什么是云原生?(二)
1. 云原生的定义 云原生指构建和运行应用以充分利用通过云技术交付模式交付的分布式计算。云原生应用旨在充分利用云技术平台特有的可扩展性、弹性和灵活性优势。 根据云原生计算基金会 (CNCF) 的定义,云原生技术可帮助企业在公有云、私有云和混合云环境中构建和…...

pytorch 47 模型剪枝实战|基于torch-pruning库代码对yolov10n模型进行剪枝
torch-pruning官方提供了基于yolov8的剪枝代码,基于此代码改进博主实现了对yolov10n模型的剪枝。虽然实现了对yolov10n模型的剪枝,剪枝目标为移除60%的通道,然而实验是失败的,针对coco数据集进行操作,剪枝前的模型map时37,剪枝后只能恢复到22,比预计下降了15个点,剪枝后…...

LeetCode_sql_day15(262.行程与用户)
描述:262. 行程和用户 - 力扣(LeetCode) 取消率 的计算方式如下:(被司机或乘客取消的非禁止用户生成的订单数量) / (非禁止用户生成的订单总数)。 编写解决方案找出 "2013-10-01" 至 "2013-10-03" 期间非禁止…...

【MySQL】详解数据库约束、聚合查询和联合查询
数据库约束 约束类型 数据库的约束类型主要包括以下几种: 主键约束(Primary Key Constraint):确保表中的每一行都有唯一的标识,且不能为NULL。 外键约束(Foreign Key Constraint):…...

bug积累
1.只写 int p[len1 len2]; 时,实际上是在使用 C99 标准中引入的变长数组(VLA, Variable Length Array)的特性。变长数组允许在栈上分配其大小在运行时确定的数组。这意味着 len1 和 len2 的值可以在程序运行时确定,但仍然可以用来…...

版本控制案例:全球虚拟制片领导者Dimension借助Perforce Helix Core简化多供应商协作,控制访问权限,确保数据资产安全(下)
创建虚拟世界和人物角色需要一系列的软件工具。但最终愿景很少是由单一工作室独立完成的。对于大型项目,工作室需要通力合作,将全球的团队成员和数字资产联合起来。 Dimension Studio——体积内容捕捉和虚拟制片领域的领导者——不断将新技术和新方法融…...

Anaconda配置envs和pcks路径
问题 原先Anaconda安装在C盘,安装很多包后只剩几个G了,为了给C盘腾空间,卸载后重新安装在了D盘,但是创建了新环境后发现环境位置依旧在C盘,安装新的包仍然会占用C盘空间。 解决办法 查看conda的配置信息 执行如下命…...

推荐10个在线搭建框架平台
前言 在开发项目的时候,首先就是要搭建一个框架。这个框架可以是纯技术框架,也可以具备一定功能的开源框架。但是在搭建框架的时候,版本的冲突,环境的配置等是新手们一直头痛的问题,在构建开源框架的时候,…...

Linux Shell--函数
前言:本博客仅作记录学习使用,部分图片出自网络,如有侵犯您的权益,请联系删除 一、简介 Shell 函数是一段可以重复使用的代码块,通过定义函数可以避免代码重复,提高脚本的可读性和可维护性。 二、定义函数…...

漏洞复现-CVE-2023-42442:JumpServer未授权访问漏洞
概述 JumpServer存在一个未授权访问漏洞。具体来说,/api/v1/terminal/sessions/ API端点的权限控制存在逻辑错误,允许攻击者匿名访问。未经身份验证的远程攻击者可以利用此漏洞下载SSH日志,并可能借此远程窃取敏感信息。值得注意的是&#x…...

【数据结构之带头双向循环链表的实现】
1.链表的分类 链表的结构有多种多样,以下情况组合起来就有8种(2x2x2)链表结构: 虽然有这么多的链表结构,但是我们实际中最常用的还是两种结构:单链表和双向带头循环链表。 无头单向非循环链表:结…...

【docker】docker数据卷与网络部署服务
Docker 网络模式 选择网络模式 Host Mode (主机模式) 特点: 容器与宿主机共享网络命名空间操作: docker run --nethost ... Container Mode (容器模式) 特点: 容器与指定容器共享网络命名空间操作: docker run --netcontainer:<container-id-or-name> ... None Mode (无…...

Spring MVC框架学习笔记
学习视频:10001 Spring MVC概述_哔哩哔哩_bilibili~11005 请求映射方式_哔哩哔哩_bilibili 目录 1.概述 Java EE三层架构 Spring MVC在三层架构中的位置 编辑 Spring MVC在表现层的作用 Spring MVC的特点 2.Spring MVC入门程序 代码实现 Spring MVC工作原理 Spring …...

LeetCode 100道题目和答案(面试必备)(一)
1.两数之和 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。 你可以按…...

OpenGL投影矩阵
OpenGL Projection Matrix OpenGL投影矩阵...

Linux中的`make`与`Makefile`:项目自动化构建工具
Linux中的make与Makefile:项目自动化构建工具 在Linux及类Unix系统中,make是一种广泛使用的自动化构建工具,它通过读取和执行Makefile(或makefile,文件名不区分大小写)中的指令来自动化编译和构建程序。Ma…...

GitHub开源项目精选:轻量级预约/预订日历组件,用React和TypeScript构建
在日常开发中,我们经常需要在项目中添加预约或预订功能。今天给大家推荐一个超级轻量级的预约/预订日历组件,它是用React和TypeScript构建的,非常适合那些需要简单易用的日历解决方案的开发者。 安装方法: 你可以选择使用npm或者y…...

闲钱放在哪里?收益稳定且又高!
家庭理财,最大的问题就是,手里这点闲钱,说多不多,但打理起来,还真的很”挠头“。 放银行,存款利率接二连三下调,利息又又又要变少了! 投资出去,看着到处的雷声隆隆&…...

【Linux】简易线程池项目
线程池是一个可以巩固一些线程相关接口 && 加强理解的一个小项目。 注意:这里的线程池使用的线程并不是Linux原生接口,而是经过封装的,具体请看线程封装,为什么不使用原生接口? 因为原生接口一旦进行pthread…...

基于vue框架的NBA球星管理系统1878g(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。
系统程序文件列表 项目功能:用户,球员,球员数据,榜单类型,联盟榜单,重要比赛回放,精彩时刻视频,视频专栏,本赛季赛程,十佳球,投票信息,投票结果 开题报告内容 基于Vue框架的NBA球星管理系统 开题报告 一、选题背景 随着互联网的普及和体育产业的蓬勃发展&#x…...

【docker】Dockerfile练习
1、overlay文件系统原理测试 cd /mnt mkdir A B C worker merged echo "From A">./A/a.txt echo "From A">./A/b.txt echo "From A">./A/c.txt echo "From B">./B/a.txt echo "From B">./B/d.txt echo &quo…...

数据可视化的魔法:Python Matplotlib库的奇妙之旅
标题:数据可视化的魔法:Python Matplotlib库的奇妙之旅 在数据科学和分析领域,数据可视化是一种将复杂数据转换为图形表示的强有力工具,它可以帮助我们更直观地理解数据。Python中的Matplotlib库是进行数据可视化的瑞士军刀&…...

Python数据科学的秘密武器:Pandas库的深度解析
标题:Python数据科学的秘密武器:Pandas库的深度解析 Python作为数据科学领域的宠儿,其强大的数据处理能力离不开Pandas库的加持。Pandas是一个开源的数据分析和操作库,它提供了快速、灵活和表达力强的数据结构,旨在使…...

云计算实训24——python基本环境搭建、变量和数据类型、数据集合、py脚本
一、python环境搭建 确保拥有阿里云镜像 查看python环境 [rootpython ~]# yum list installed | grep python 查看epel是否安装 [rootpython ~]# yum list installed | grep epel 安装epel [rootpython ~]# yum -y install epel-release.noarch 查看是否安装python3 [rootpyt…...

深入了解网络性能监控(NPM):优化网络性能的关键
目录 网络性能监控(NPM)是什么? 关键网络性能指标 案例分享:如何利用NPM优化网络性能 实用技巧:如何高效运维你的网络 结论 随着企业依赖于互联网和内部网络进行业务运营,网络的稳定性和性能显得尤为重…...

Vue引入使用iconfont字体图标
由于element-ui或element-plus提供的图标有时候并不能满足日常需求,所以这篇介绍一下前端引入阿里巴巴矢量图标库使用,不止是vue使用,不限于vue2、vue3,html或是其他框架也是同样的道理,只要引入都是同样可以使用的。 1. 首先进入阿里巴巴矢量图标库官网 官网:https://…...

Doc2Vec
Doc2Vec 是一种扩展自 Word2Vec 的算法,它不仅可以生成词向量,还可以生成句子或文档的向量。下面是一个使用 Doc2Vec 比较两个句子的具体过程: 步骤 1: 训练 Doc2Vec 模型 首先,你需要有一个训练好的 Doc2Vec 模型。训练过程大致…...

MES生产过程透明管理,实施掌握生产每个环节
MES(制造执行系统)生产过程透明管理,旨在通过集成多种技术手段和管理模块,实现对生产过程的实时监控和精准掌握,确保每个生产环节都能被清晰地记录和追踪。以下是对MES生产过程透明管理的详细阐述: 一、MES…...