# 空间网格编码接口参考 `yukon_geogridcoder` 模块提供基于空间网格编码体系的编码生成、属性获取、类型转换、网格处理与空间分析等功能。当前支持 GeoSOT 和北斗两种网格编码体系,提供 `GeoSOTGrid`(单一 GeoSOT 编码)和 `GeoGridCode`(通用多编码体系)两种数据类型,覆盖二维平面与三维立体网格场景。使用前需在数据库中创建 `yukon_geogridcoder` 扩展。 ## 数据类型 ### GeoSOTGrid 基于 GeoSOT 网格编码体系的空间网格数据类型。 - 支持二维和三维网格编码。 - 支持 B-Tree 索引和 GIN(Generalized Inverted Index) 索引。 ### GeoGridCode 通用空间网格编码数据类型。 - 支持多种编码类型,当前支持 GeoSOT 和北斗网格编码,与 GeoSOTGrid 不同,该类型在存储网格编码的同时保留编码体系标识,支持不同编码体系之间的转换。举例:`beidou;N050K0040010700`。 - 支持二维和三维网格编码。 - 支持 B-Tree 索引和 GIN(Generalized Inverted Index) 索引。 ## 网格生成函数 ### ST_GeoSOTGrid 获取 geometry 对象的网格编码,默认获取对象的最小外包网格编码。也可设置指定层级,获取对象指定层级的空间网格编码。 **语法** ```sql geosotgrid[] ST_GeoSOTGrid(geometry geom, integer level); geosotgrid[] ST_GeoSOTGrid(geometry geom); ``` | 参数 | 类型 | 说明 | |------|------|------| | geom | geometry | 几何对象,当前坐标系仅支持 SRID=4490 | | level | integer | 网格编码层级 | **返回:** `geosotgrid[]` 类型数组,以二进制形式存储。 **示例** ```sql SELECT ST_GeoSOTGrid(st_geomfromtext('POINT(116.315 39.91027777777778)', 4490), 15); -- 输出 -- -------------------------- -- {074EACB0000000000000F0000} ``` ### ST_GeoSOTGridZ 返回 z 方向上指定层级的网格编号,用海拔基准面开始向上的第 N 层网格来表示。 **语法** ```sql integer ST_GeoSOTGridZ(double precision altitude, integer level); ``` | 参数 | 类型 | 说明 | |------|------|------| | altitude | double precision | 海拔高度 | | level | integer | 网格编码层级 | **返回:** `integer`,Z 方向上的网格编号。 **示例** ```sql SELECT ST_GeoSOTGridZ(9300, 15); -- 输出 -- ---------- -- 5 ``` ### ST_GeoSOTGridAgg 获取 `geometry` 对象在指定层级范围内的网格编码。 **语法** ```sql geosotgrid[] ST_GeoSOTGridAgg(geometry geom, integer level_max, integer level_min); ``` | 参数 | 类型 | 说明 | |------|------|------| | geom | geometry | 几何对象,当前坐标系仅支持 SRID=4490 | | level_max | integer | 最大编码层级 | | level_min | integer | 最小编码层级 | **返回:** `geosotgrid[]` 类型数组,包含指定层级范围内的网格编码。 **示例** ```sql SELECT ST_GeoSOTGridAgg('srid=4490;polygon((0.1 0.1, 0.2 0.2, 0.3 0.1, 0.1 0.1))'::geometry, 11, 9); -- 输出 -- -------------------------- -- {0000000000000000000B0000,0000040000000000000B0000} ``` ### ST_AsGeoGridCode 生成指定编码体系下的网格编码数组,当前版本支持 GeoSOT 和北斗网格编码。 **语法** ```sql geogridcode[] ST_AsGeoGridCode(geometry geom, integer level, text type); ``` | 参数 | 类型 | 说明 | |------|------|------| | geom | geometry | 几何对象,当前坐标系仅支持 SRID=4490 | | level | integer | 编码层级,geosot 支持 1-32 层级,beidou 支持 1-10 层级 | | type | text | 编码类型,支持 `'geosot'`、`'beidou'` | **返回:** `geogridcode[]` 类型数组。 **示例** ```sql SELECT ST_AsGeoGridCode(ST_GeomFromText('POINTZ(116.37547175931773 40.0020616531778 35)', 4490), 4, 'beidou'); -- 输出 -- -------------------------- -- {beidou;N050K0040010700} ``` ### ST_GeoGridCodeMixedLevel 对 POLYGONSURFACE Z(三维多面体表面)几何体生成混合层级网格。当前支持球面输入,适用于实时飞行器坐标的安全预警场景,可生成以飞行器坐标为中心的球状缓冲区网格,用于警戒空域侵入、建筑障碍接近、偏航告警等。 GeoGridCodeMixedLevel **语法** ```sql geogridcode[] ST_GeoGridCodeMixedLevel(geometry geom, integer level, text type); ``` | 参数 | 类型 | 说明 | |------|------|------| | geom | geometry | 待生成网格的几何体,支持三维几何体(`POLYGONSURFACE Z`),SRID 必须为 4490 | | level | integer | 网格层级,生成缓冲区网格的最高层级 | | type | text | 待生成的网格编码类型,支持 `'geosot'`、`'beidou'` | **返回:** `geogridcode[]` 类型数组,包含输入几何体的混合层级网格。 **示例** ```sql SELECT ST_GeoGridCodeMixedLevel(geom, 15, 'geosot') FROM aircraft_position; ``` ## 属性获取函数 ### ST_GetLevel 获取网格对象的编码层级。 **语法** ```sql integer ST_GetLevel(grid geosotgrid); ``` | 参数 | 类型 | 说明 | |------|------|------| | grid | geosotgrid | 网格对象 | **返回:** 网格编码层级(integer)。 **示例** ```sql SELECT ST_GetLevel('0000040000000000000B0000'); -- 输出 -- -------------------------- -- 11 ``` ### ST_GetLevelExtremum 获取网格编码数组的编码层级范围。 **语法** ```sql integer[] ST_GetLevelextremum(geosotgrid[] grids); ``` | 参数 | 类型 | 说明 | |------|------|------| | grids | geosotgrid[] | 网格编码数组 | **返回:** 网格编码层级范围(integer[]),形式为 `{level_min, level_max}`。 **示例** ```sql SELECT ST_GetLevelextremum(array['074526EEF400000013130000','07452C4701C0000013150000'::geosotgrid]); -- 输出 -- -------------------------- -- {19,21} ``` ### ST_HasZ 判断网格编码是否包含 Z 方向。 **语法** ```sql boolean ST_HasZ(geosotgrid grid); ``` | 参数 | 类型 | 说明 | |------|------|------| | grid | geosotgrid | 网格对象 | **返回:** 包含 Z 方向返回 `true`,否则返回 `false`。 **示例** ```sql SELECT ST_HasZ(unnest(ST_GeoSOTGrid(st_geomfromtext('POINT(116.315 39.91027777777778)', 4490), 15))); -- 输出 -- -------------------------- -- false ``` ### ST_AltitudeFromGeoSOTGridZ 返回 Z 方向指定层级下第 N 个网格对应的海拔高度。 **语法** ```sql double precision ST_AltitudeFromGeoSOTGridZ(integer z_num, integer level); ``` | 参数 | 类型 | 说明 | |------|------|------| | z_num | integer | Z 方向上的第几个网格 | | level | integer | 网格编码层级 | **返回:** 海拔高度(单位:米)。 **示例** ```sql SELECT ST_AltitudeFromGeoSOTGridZ(5, 15); -- 输出 -- -------------------------- -- 9203.23364591971 ``` ## 转换函数 ### ST_AsText 将网格编码转换为标准格式的文本字符串。支持批量转换。 **语法** ```sql text ST_AsText(geogridcode grid); text ST_AsText(geosotgrid[] grids); -- 批量转换 ``` | 参数 | 类型 | 说明 | |------|------|------| | grid | geogridcode | 网格编码对象 | | grids | geosotgrid[] | 网格编码数组 | **返回:** 网格编码的文本表示,二维格式如 `G001310322-230230`。 **示例** ```sql SELECT ST_AsText('074EACB000000000000F0000'::geosotgrid); -- 输出 -- -------------------------- -- G001310322-230230 ``` ### ST_GeoSOTGridFromText 将文本格式的网格编码转换为 `geosotgrid` 类型。支持二维和三维网格编码字符串。 **语法** ```sql geosotgrid ST_GeoSOTGridFromText(cstring geosotgrid2d); geosotgrid ST_GeoSOTGridFromText(cstring geosotgrid2d, cstring geosotgrid_z); ``` | 参数 | 类型 | 说明 | |------|------|------| | geosotgrid2d | cstring | 二维网格编码字符串 | | geosotgrid_z | cstring | 三维网格编码 Z 方向字符串 | **返回:** `geosotgrid` 类型的网格编码。 **示例** ```sql SELECT ST_GeoSOTGridFromText('G001310322-230230', '101'); -- 输出 -- -------------------------- -- 00B21A4984C0000000000104000F0001 ``` ### ST_GeomFromGeoSOTGrid 将 `geosotgrid` 网格编码转换为几何对象。二维网格返回 `POLYGON`,三维网格返回 `POLYHEDRALSURFACE Z`。 **语法** ```sql geometry ST_GeomFromGeoSOTGrid(geosotgrid grid); geometry[] ST_GeomFromGeoSOTGrid(geosotgrid[] grids); ``` | 参数 | 类型 | 说明 | |------|------|------| | grid | geosotgrid | 网格编码 | | grids | geosotgrid[] | 网格编码数组 | **返回:** 网格编码对应的 `geometry` 对象或数组。 **示例** ```sql SELECT ST_ASTEXT(ST_GeomFromGeoSOTGrid('074EACB000000000000F0000'::geosotgrid)); -- 输出 -- -------------------------- -- POLYGON ((116.3 39.9, 116.3 39.916666666666664, 116.31666666666666 39.916666666666664, 116.31666666666666 39.9, 116.3 39.9)) ``` ### ST_GeomFromGeoGridCode 将 `geogridcode` 网格编码转换为几何对象。二维网格返回 `POLYGON`,三维网格返回 `POLYHEDRALSURFACE Z`。 **语法** ```sql geometry ST_GeomFromGeoGridCode(grid geogridcode) ``` | 参数 | 类型 | 说明 | |------|------|------| | grid | geogridcode | 网格编码 | **返回:** 网格编码对应的 `geometry` 对象。 **示例** ```sql SELECT ST_AsText(ST_GeomFromGeoGridCode(unnest(st_asgeogridcode('SRID=4490;POINTZ(104 36 50)',22,'geosot'))));; -- 输出 -- -------------------------- -- POLYGON ((116.3 39.9, 116.3 39.916666666666664, 116.31666666666666 39.916666666666664, 116.31666666666666 39.9, 116.3 39.9)) ``` ### ST_PointsFromGeoGridCode 计算网格编码的顶点坐标。二维网格返回四个顶点坐标,三维网格返回八个顶点坐标。 **语法** ```sql double[] ST_PointsFromGeoGridCode(grid geogridcode); ``` | 参数 | 类型 | 说明 | |------|------|------| | grid | geogridcode | 网格编码 | **返回:** 网格编码对应的顶点坐标数组,形式为 `{xmin, xmax, ymin, ymax, zmin, zmax}`。 **示例** ```sql SELECT ST_PointsFromGeoGridCode(ST_AsGeoGridCode(ST_GeomFromText('POINTZ(116.315 39.91027777777778 50)', 4490), 7, 'beidou')); -- 输出 -- -------------------------- -- {116.31492614746094,116.31500244140625,39.910274505615234,39.91035079956055,45.9831657409668,53.64706039428711} ``` ### ST_GridConvert 在不同网格编码体系之间进行转换。当前支持 GeoSOT 与北斗编码之间的双向转换。 > **注意:** 并非所有层级之间都存在可转换关系,若不存在可转换关系,会提示当前转换不支持。 **语法** ```sql geogridcode ST_GridConvert(geogridcode grid, text codename); ``` | 参数 | 类型 | 说明 | |------|------|------| | grid | geogridcode | 网格编码 | | codename | text | 目标网格编码类型,支持 `'geosot'`、`'beidou'` | **返回:** 转换后的 `geogridcode` 类型网格编码。 **示例** ```sql SELECT ST_GridConvert('geosot;G001123220-202011-102300.00,110'::geogridcode, 'beidou'); -- 输出 -- -------------------------- -- beidou;N048H004502030093000006 ``` ## 网格处理函数 ### ST_Aggregate 将精细层级网格编码聚合为指定粗糙层级的网格编码。 **语法** ```sql geosotgrid ST_Aggregate(geosotgrid grid, integer level); geosotgrid[] ST_Aggregate(geosotgrid[] grids, integer level); ``` | 参数 | 类型 | 说明 | |------|------|------| | grid | geosotgrid | 网格编码 | | grids | geosotgrid[] | 网格编码数组 | | level | integer | 目标粗糙层级的网格编码层级 | **返回:** 聚合后的 `geosotgrid` 或 `geosotgrid[]` 类型网格编码。 **示例** ```sql SELECT ST_Aggregate('074EA000000000000A0A0000'::geosotgrid, 9); -- 输出 -- -------------------------- -- 074E80000000000009090000 ``` ### ST_GeoGridCodeLevelTransform 将指定层级的网格展开为最小到最大层级范围内的自适应混合层级网格编码。 **语法** ```sql geogridcode[] ST_GeoGridCodeLevelTransform(grid geogridcode, integer min_level, integer max_level); ``` | 参数 | 类型 | 说明 | |------|------|------| | grid | geogridcode | 网格编码 | | min_level | integer | 展开后的最小层级 | | max_level | integer | 展开后的最大层级 | **返回:** 最小到最大层级的自适应混合层级网格编码。 **示例** ```sql SELECT ST_GeoGridCodeLevelTransform(ST_GeoSOTGridFromText('G001123220-200200-000000.000', '0'), 21, 24); -- 输出 -- -------------------------- -- {0094D208040000000000000000180001,0094D208040000000000000000170001,0094D208040000000000000000160001,0094D208040000000000000000150001} ``` ## 空间关系函数 ### && 判断两个网格编码数组是否存在相交。该操作符支持同一层级和不同层级网格的相交判断。 > **注意:** 对两张表进行相交查询时,若两张表均使用了 GIN 索引,只有当两个网格层级相同且网格编码类型相同,才能判定相交;对两个单值进行比较时则无需考虑层级和编码类型是否相同。 **语法** ```sql boolean &&(geosotgrid[] left_grid, geosotgrid[] right_grid); boolean &&(geogridcode[] left_grid, geogridcode[] right_grid); ``` | 参数 | 类型 | 说明 | |------|------|------| | left_grid | geosotgrid[] / geogridcode[] | 左侧网格编码数组 | | right_grid | geosotgrid[] / geogridcode[] | 右侧网格编码数组 | **返回:** 存在相交则返回 `true`,不存在相交则返回 `false`。 **示例** ```sql -- 不同层级网格相交判断 SELECT ST_AsGeoGridCode(ST_GeomFromText('POINTZ(116.315 39.91027777777778 50)', 4490), 15, 'geosot') && ST_AsGeoGridCode(ST_GeomFromText('POINTZ(116.315 39.91027777777778 50)', 4490), 16, 'geosot'); -- 输出 -- ------------- -- true ``` ### @> 判断左侧网格编码数组是否包含右侧网格编码数组。即 `gridsB` 中的每个网格是否都能被 `gridsA` 中的某个网格包含(父子层级或同层级相同编码)。 **语法** ```sql boolean @>(geosotgrid[] gridsA, geosotgrid[] gridsB); ``` | 参数 | 类型 | 说明 | |------|------|------| | gridsA | geosotgrid[] | 左侧网格编码数组 | | gridsB | geosotgrid[] | 右侧网格编码数组 | **返回:** 若 `gridsA` 包含 `gridsB` 则返回 `true`,否则返回 `false`。 **示例** ```sql -- 大区域网格是否包含小区域网格 SELECT ST_GeoSOTGrid(ST_MAKEENVELOPE(1, 1, 2, 2, 4490), 15) @> ST_GeoSOTGrid(ST_MAKEENVELOPE(1.2, 1.2, 1.8, 1.8, 4490), 15); -- 输出 -- ------------- -- true ``` ### <@ 判断左侧网格编码数组是否被右侧网格编码数组包含。即 `gridsA` 中的每个网格是否都被 `gridsB` 中的某个网格包含(父子层级或同层级相同编码)。 **语法** ```sql boolean <@(geosotgrid[] gridsA, geosotgrid[] gridsB); ``` | 参数 | 类型 | 说明 | |------|------|------| | gridsA | geosotgrid[] | 左侧网格编码数组 | | gridsB | geosotgrid[] | 右侧网格编码数组 | **返回:** 若 `gridsA` 被 `gridsB` 包含则返回 `true`,否则返回 `false`。 **示例** ```sql -- 小区域网格是否被大区域网格包含 SELECT ST_GeoSOTGrid(ST_MAKEENVELOPE(1.5, 1.5, 2, 2, 4490), 15) <@ ST_GeoSOTGrid(ST_MAKEENVELOPE(1, 1, 2, 2, 4490), 15); -- 输出 -- ------------- -- true ``` ## 空间分析函数 ### ST_IntersectionGrids 网格相交查询函数。 **语法** ```sql geogridcode[] ST_IntersectionGrids(ob_schema_name text, ob_table_name text, ob_column_name text, grids geogridcode[]); ``` | 参数 | 类型 | 说明 | |------|------|------| | ob_schema_name | text | 待查询表所属模式(schema)的名称 | | ob_table_name | text | 待查询表的名称 | | ob_column_name | text | 待查询表中网格编码字段列的名称,数据类型须为 `geogridcode[]` | | grids | geogridcode[] | 用于查询的网格集合,所有查询网格的类型(geosot或北斗)必须一致 | **返回:** `geogridcode[]` 类型数组,包含待查询表中所有与查询网格相交的网格编码。 **示例** ```sql SELECT ST_IntersectionGrids('public', 'building_grid', 'grids', buffer_grids) FROM search_area; ``` ### ST_GridCodeFindMultiDronePath 在三维网格空间中为多组起终点对搜索最优飞行路径,支持建筑物避让、禁飞区约束等场景。该函数基于 A* 算法在网格空间中进行路径搜索,将复杂的三维几何求交运算转化为高效的网格查询,适用于无人机配送、设施巡检、应急运输等低空应用。 ![alt](../_static/images/demo_lowaltitude/grid_sample.png) **语法** ```sql SETOF ( start_point geometry, end_point geometry, geogridcode[] ) ST_GridCodeFindMultiDronePath( path_pairs geometry[], obstacle_configs jsonb, geogrid_level integer, allow_diagonal_movement boolean, max_iterations integer, heuristic_weight double precision, custom_costs Grid3DCost, buffer_distance_meters double precision ); ``` | 参数 | 类型 | 说明 | |------|------|------| | path_pairs | geometry[] | 起终点坐标对数组。每组路径以 `ARRAY[start_geom, end_geom]` 表示,支持 `POINTZ` 三维坐标,SRID 必须为 4490 | | obstacle_configs | jsonb | 障碍物配置,详见下方参数详解 | | geogrid_level | integer | 网格编码层级,用于路径搜索的网格分辨率,通常和障碍物网格层级保持一致 | | allow_diagonal_movement | boolean | 是否允许对角线移动,默认为 `false`,详见下方参数详解 | | max_iterations | integer | 最大搜索迭代次数,默认为 `100000`。路径较长或障碍物密集时可适当增大 | | heuristic_weight | double precision | A* 搜索启发式权重,默认为 `1.0`。增大此值可提升搜索速度,但可能牺牲路径最优性 | | custom_costs | Grid3DCost | 自定义代价函数,详见下方参数详解 | | buffer_distance_meters | double precision | 路径安全缓冲距离(单位:米),详见下方参数详解 | **参数详解** **obstacle_configs**:支持三维网格和二维几何面作为障碍物。每个障碍物配置项需包含以下字段: | 字段 | 类型 | 说明 | |------|------|------| | schema_name | text | 障碍物数据表所在的模式(schema)名称 | | table_name | text | 障碍物数据表的名称 | | column_name | text | 当 `is_2d` 为 `false` 时存储三维网格编码,为 `true` 时存储二维几何面的空间几何信息 | | is_2d | boolean | `false` 表示三维网格障碍物,`true` 表示二维几何面(如禁飞区) | | min_level | integer | 该障碍物源生效的最小网格编码层级 | | max_level | integer | 该障碍物源生效的最大网格编码层级 | | where_clause | text| 附加的 SQL WHERE 子句,用于查询障碍物表时进行额外过滤,如 `"height > 50"` | **allow_diagonal_movement**:是否允许路径在网格中进行对角线移动。对于低空飞行,建议保持默认值 `false`,保持与网格方向一致的飞行姿态更平稳、更安全。 ![alt](../_static/images/demo_lowaltitude/diag.png) **buffer_distance_meters**:路径安全缓冲距离,单位为米。设置此参数后,函数将在计算出的路径周围生成一个安全缓冲区,以确保飞行器在飞行过程中与障碍物保持一定的安全距离。 **custom_costs**:自定义网格移动代价(Grid3DCost 类型)。为特定网格设置更高的代价值,引导路径避开不安全区域或偏好更优路线。格式:`ROW(网格编码数组, 代价值)::Grid3DCost`。 **返回:** 返回多行记录(SETOF),每行包含: | 字段 | 类型 | 说明 | |------|------|------| | start_point | geometry | 路径起点坐标 | | end_point | geometry | 路径终点坐标 | | path | geogridcode[] | 从起点到终点的网格编码序列,按飞行顺序排列 | **示例** ```sql SELECT start_point, end_point, path FROM ST_GridCodeFindMultiDronePath( ARRAY[ ARRAY[ 'SRID=4490;POINTZ(116.374115 39.989219 34.615913)'::geometry ] ], '[ /* 3D建筑物网格障碍物配置 */ { "schema_name": "public", "table_name": "building_grid24", "column_name": "grids", "is_2d": false, "min_level": 24, "max_level": 24 }, /* 2D禁飞区几何面障碍物配置 */ { "schema_name": "public", "table_name": "no_fly_zone", "column_name": "geom", "is_2d": true, "min_level": 24, "max_level": 24 ]'::JSONB, 24, buffer_distance_meters => 3.0 ); ```