本文介绍了地理网格模型的用途、基本构成和快速入门等内容。
模型用途
简介
地理网格模型是一种统一、简单的地理空间划分和定位参考系统,依据统一规则,将地面区域按照一定经纬度或地面距离进行连续分割,并将空间不确定性控制在一定范围内,形成规则多边形,每个多边形均称为格网单元,从而构成分级、分层次的多级格网体系,实现地面空间离散化,并赋予统一编码。
Ganos GeomGrid是对象关系型数据库PostgreSQL兼容版本(PolarDB PostgreSQL版)的一个时空引擎扩展,用于表达和处理地理网格对象。此模型主要提供了地理网格以及地理网格数组类型的空间操作函数,空间关系判断函数,以及与Ganos中其他数据类型的转换计算函数
GeomGrid在Ganos中指代地理网格数据类型。地理网格是一种再现地球表面的多边形网格单元集合,可以用于表示地物在地理空间中的位置信息,融合其他各类时空数据。每个网格单元都会进行编码,网格与编码是一一对应的。三维地理网格不只考虑经纬度,还把高度维纳入剖分和编码范围。
GeomGrid模块目前涵盖GeoSOT和H3两种地理网格。GeoSOT是中国提出的一套地球空间剖分理论,并在此基础上发展出的一种离散化、多尺度区域位置标识体系。H3是Uber研发的一种覆盖全球表面的二维地理网格,采用的基本网格是正六边形。
功能概述
GeomGrid支持地理网格的输入输出,空间操作和空间关系判断:
支持Text、Bytea、Geometry、Meshgeom、Sfmesh、Vomesh等类型与GeomGrid类型的互相转换。
支持网格层级获取,网格坐标获取,父子节点计算,网格合并和网格剖分等空间查询操作。
支持geomgrid与geometry、meshgeom、sfmesh、vomesh以及gemogrid类型之间的空间关系判断操作。
更多内容请参见GeomGrid SQL参考。
主要业务场景
Ganos GeomGrid可支持多种业务场景,最常见的包括以下几个:
网格查询
给定一个网格或网格数组,查询是否与数据库中存储的网格相交。支持退化网格,即可以通过子网格查出父网格,反之亦然。例如在停放共享单车时,停放区的网格码存在数据库中,而用户的位置可以转换为网格码到库中搜索,找出最近的停放区。网格查询也常用于关联不同的图层,把不同图层的地物转化为网格存储,然后根据某一网格查出所有相关图层的地物。
网格聚合
物流、快送等行业中经常以网格为单位统计时空要素。例如船或车的轨迹数据可经过网格聚合生成热力图,先把轨迹转化为网格表达,然后统计每个网格中的轨迹数量作为热力进行绘制。再例如以街道为单位收集的人口数据可分配至网格进行可视化表达。
网格寻路
无人机在复杂环境下可以借助三维网格进行航线规划,通过网格设置空间障碍物的穿越开销,借助路径规划算法可得到网格路径。
基本构成
概述
基于GeoSOT和H3地理网格的理论框架,在Ganos GeomGrid模块中,两种网格分别被实现成GeomGrid数据类型和H3Grid数据类型。
编码
GeoSOT
GeoSOT将地球通过简单投影变换到平面,将180°×360° 地球表面空间扩展为512°×512°,并将该空间作为第0级剖分面片,且面片中心与赤道和本初子午线的交点重合。在此基础上,对第0级剖分面片进行递归四叉剖分,直到32级。这样,整个地球表面经纬度空间在经线方向和纬线方向可严格的整型二分,由此将整个地球分割为大到全球、小到厘米级的整度、整分和整秒的层次网格。
GeoSOT二维网格最长的编码位为32位四进制数值编码。第1-9位是度级网格编码,第10-15位是分级网格编码,第16-21位是秒级网格编码,第22-32位是秒以下网格编码,编码长度即为网格层级。
经度和纬度均采用A°B′C.D″
的表达形式,将度由十进制数转换成8bit的二进制数A2;将分由十进制数转换成6bit的二进制数B2;将秒由十进制数转换成6bit的二进制数C2;将秒的小数部分由十进制数转换成11bit的二进制数D2;将二进制数A2、B2、C2 以及D2顺次拼接为31bit的二进制数。将纬度前置,经度后置,采用莫顿交叉的方式生成62位的混合代码。在混合代码前加上G0、G1、G2或G3即可得到网格代码。G0对应东北半球,G1对应西北半球,G2对应东南半球,G3对应西南半球。
GeoSOT三维网格在二维网格的基础上增加了高度域。为保证高度域的划分与经纬度一致,对应地表1º 网格,地面向上延伸至高空256个网格,向下延伸至地心256个网格。而后对应不同层级进行二分处理得到垂直方向的层数,并以此进行二进制编码,与经纬度编码莫顿交叉形成三维网格编码。
H3
H3采用的投影方式是以二十面体近似地球球体,如下图所示,这个二十面体的每一个面都是球面三角形,有12个顶点,称为球形二十面体。
如下图所示,H3在每个三角面上都划分相同排列方式的六边形,进而将全球划分成122个基本单元,然后对每个基本单元再进行六边形剖分。
H3从122个基本单元开始,对每个单元递归地细分为7个子单元,如下图所示,以编号为20的基本单元为例进行分解。
H3的编码值最多占63个比特位,可以用一个长整型表示,通常序列化为十六进制字符串。H3编码的位布局提供了一个相对紧凑的结构,用于存储有关给定索引的信息并定义其地理位置,如下图所示。
索引
索引通过将数据组织到搜索树中来加速搜索,避免大数据量时全局“顺序扫描”带来的延迟。GeomGrid模块适用的索引主要包括以下几种:
索引名称 | 索引简介 | 索引特点 |
Btree | Btree索引作用于地理网格类型,通过对网格编码的大小比对进行查找。 | Btree是数据库最通用的索引方法,可以加速的查询类型也最多。 |
GiST | GiST索引作用于地理网格类型,提供地理网格外包框的相交和包含查询。 | GiST此处实现Rtree的结构,对于网格空间查询效率很高。 |
GridGin | GridGin索引拓展了Gin索引,可作用于地理网格类型和地理网格数组类型,提供了相交和包含关系判断,并进行了优化处理。 | GridGin支持退化网格查询,并可以加速网格聚合计算。 |
快速入门
简介
快速入门文档帮助用户快速理解 Ganos GeomGrid 引擎的基本用法,包括扩展创建、建表、插入数据、计算网格码、创建索引、查询等内容。
语法说明
创建扩展。
CREATE EXTENSION Ganos_GeomGrid CASCADE;
说明建议将扩展安装在public模式下,避免权限问题。
CREATE extension ganos_geometry WITH schema public cascade;
GeoSOT网格操作。
创建具有网格码的表。
-- 可以为几何 CREATE TABLE t_grid(id integer, geom geometry, -- 几何对象 grid1 geomgrid[], -- 网格码,精度1 grid2 geomgrid[], -- 网格码,精度2 grid3 geomgrid[] -- 网格码,精度3 );
插入数据。
--插入点数据 INSERT INTO t_grid(id, geom) VALUES (1, ST_GeomFromText('POINT(116.31522216796875 39.910277777777778)', 4490)), (2, ST_GeomFromText('POINT(116.31522217796875 39.910277776777778)', 4490)), (3, ST_GeomFromText('POINT(116.31522217797875 39.910277776787778)', 4490)), (4, ST_GeomFromText('POINT(116.31522227796875 39.910277776775778)', 4490)); -- 插入面数据 INSERT INTO t_grid(id, geom) VALUES(5, 'SRID=4490;POLYGON((-0.08077 -0.02814, 0.0482 -0.03, 0.07426 0.03724, -0.08077 -0.02814))'::geometry); -- 插入三维数据 INSERT INTO t_grid(id, geom) VALUES(6, 'SRID=4490;CIRCULARSTRING Z (-63.597471 44.8071 20,-63.597 44.807 0,-63.5974 44.807 40)'::geometry);
计算网格码。
-- 创建不同精度的网格码 UPDATE t_grid SET grid1 = ST_AsGrid(geom, 10), grid2 = ST_AsGrid(geom, 15), grid3 = ST_AsGrid(geom, 26); -- 生成退化网格码 UPDATE t_grid SET grid1 = st_asgrid(geom, 18, true) WHERE id = 5; -- 生成三维网格码 UPDATE t_grid SET grid1 = st_as3dgrid(geom, 25) WHERE id=6;
对网格码创建索引。
-- 针对不同精度的网格码创建GIN索引 CREATE INDEX idx_grid_gin1 ON t_grid USING GIN(grid1); CREATE INDEX idx_grid_gin2 ON t_grid USING GIN(grid2); CREATE INDEX idx_grid_gin3 ON t_grid USING GIN(grid3);
查询。
-- 完全在某个网格中 SELECT id FROM t_grid WHERE grid2 = ARRAY[ST_GridFromText('G001310322230230')]; -- 和某个网格相交 SELECT id FROM t_grid WHERE grid3 @> ARRAY[ST_GridFromText('G00131032223023031031033223')]; -- 和某些网格相交 SELECT id FROM t_grid WHERE grid3 && ARRAY[ST_GridFromText('G00131032223023031031211001'), ST_GridFromText('G00131032223023031031211111')]; -- 和某个几何对象在网格上相交 SELECT id FROM t_grid WHERE grid3 && ST_AsGrid( ST_GeomFromText('LINESTRING(116.31522216796875 39.910277777777778, 116.31522217797875 39.910277776787778)', 4490), 26);
H3网格操作。
建表。
CREATE TABLE h3_grid( id integer, geom geometry, -- 几何对象 h3 h3grid[] -- H3对象类型 );
插入数据。
INSERT INTO h3_grid VALUES (1, 'POINT(102.5 25.7)'::geometry); INSERT INTO h3_grid VALUES (2, 'POLYGON((-0.08077 -0.02814, 0.0482 -0.03, 0.07426 0.03724, -0.08077 -0.02814)'::geometry);
计算H3网格码。
-- 普通网格码 UPDATE h3_grid SET h3 = ST_AsH3Grid(geom, 7); -- 退化网格码 UPDATE h3_grid SET h3 = ST_AsH3Grid(geom, 7, true);
建立索引。
CREATE INDEX h3_grid_btree ON h3_grid(h3);
查询。
-- 显示H3编码 SELECT st_astext(h3[1]) FROM h3_grid; -- 搜索 SELECT * FROM h3_grid WHERE h3 > ARRAY[ST_H3FromText('884a126689fffff')];
删除扩展(可选)。
DROP EXTENSION Ganos_GeomGrid CASCADE;
SQL参考
详细SQL手册请参见GeomGrid SQL参考。