h3

H3六边形层级索引支持

概览

扩展包名版本分类许可证语言
pg_h34.2.3GISApache-2.0C
ID扩展名BinLibLoadCreateTrustReloc模式
1530h3-
1531h3_postgis-
相关扩展postgis q3c pg_geohash postgis_topology postgis_raster postgis_sfcgal postgis_tiger_geocoder address_standardizer
下游依赖h3_postgis

pgdg missing el8.x86.pg17 and el8.x86.pg18

版本

类型仓库版本PG 大版本包名依赖
EXTPGDG4.2.31817161514pg_h3-
RPMPGDG4.2.31817161514h3-pg_$v-
DEBPGDG4.2.31817161514postgresql-$v-h3-
OS / PGPG18PG17PG16PG15PG14
el8.x86_64PGDG MISSPGDG MISS
el8.aarch64
el9.x86_64
el9.aarch64
el10.x86_64
el10.aarch64
d12.x86_64
d12.aarch64
d13.x86_64
d13.aarch64
u22.x86_64
u22.aarch64
u24.x86_64
u24.aarch64

安装

您可以直接安装 pg_h3 扩展包的预置二进制包,首先确保 PGDG 仓库已经添加并启用:

pig repo add pgdg -u          # 添加 PGDG 仓库并更新缓存

使用 pig 或者是 apt/yum/dnf 安装扩展:

pig install pg_h3;          # 当前活跃 PG 版本安装
pig ext install -y pg_h3 -v 18  # PG 18
pig ext install -y pg_h3 -v 17  # PG 17
pig ext install -y pg_h3 -v 16  # PG 16
pig ext install -y pg_h3 -v 15  # PG 15
pig ext install -y pg_h3 -v 14  # PG 14
dnf install -y h3-pg_18       # PG 18
dnf install -y h3-pg_17       # PG 17
dnf install -y h3-pg_16       # PG 16
dnf install -y h3-pg_15       # PG 15
dnf install -y h3-pg_14       # PG 14
apt install -y postgresql-18-h3   # PG 18
apt install -y postgresql-17-h3   # PG 17
apt install -y postgresql-16-h3   # PG 16
apt install -y postgresql-15-h3   # PG 15
apt install -y postgresql-14-h3   # PG 14

创建扩展

CREATE EXTENSION h3;

用法

h3-pg: Uber 的 H3 六边形层次地理空间索引系统的 PostgreSQL 绑定

该扩展为 H3 核心库(Uber 的六边形层次地理空间索引系统)提供 PostgreSQL 绑定。完整 API 参考请参见 H3 文档

通常,所有函数都从 H3 的 camelCase 重命名为 SQL 的 snake_case,并加上 h3_ 前缀。

CREATE EXTENSION h3;

SELECT h3_latlng_to_cell(POINT('37.3615593,-122.0553238'), 5);
  h3_latlng_to_cell
-------------------
 85e35e73fffffff

基础类型

h3index 类型是一个无符号 64 位整数,表示任何 H3 对象(六边形、五边形、有向边等),以 16 字符的十六进制字符串显示,如 '8928308280fffff'

索引函数

这些函数用于查找包含指定坐标的 H3 索引,以及获取 H3 索引的中心和边界。

-- 在指定分辨率(0-15)索引一个位置
SELECT h3_latlng_to_cell(POINT('37.3615593,-122.0553238'), 5);

-- 查找索引的质心
SELECT h3_cell_to_latlng('85283473fffffff'::h3index);

-- 查找索引的边界多边形
SELECT h3_cell_to_boundary('85283473fffffff'::h3index);

使用 SET h3.extend_antimeridian TO true 可在跨越 180 度经线时扩展坐标。

索引检查函数

-- 获取索引的分辨率(0-15)
SELECT h3_get_resolution('85283473fffffff'::h3index);

-- 获取基础单元格编号
SELECT h3_get_base_cell_number('85283473fffffff'::h3index);

-- 验证 H3 索引
SELECT h3_is_valid_cell('85283473fffffff'::h3index);

-- 检查索引是否为五边形
SELECT h3_is_pentagon('85283473fffffff'::h3index);

-- 检查分辨率是否为 Class III 方向
SELECT h3_is_res_class_iii('85283473fffffff'::h3index);

-- 查找索引相交的所有二十面体面
SELECT h3_get_icosahedron_faces('85283473fffffff'::h3index);

网格遍历函数

网格遍历可以查找起始单元格附近的单元格,以及确定从一个单元格到另一个单元格的遍历路径。

-- 获取距起点 k 步以内的所有索引
SELECT h3_grid_disk('85283473fffffff'::h3index, 2);

-- 带距离的索引
SELECT * FROM h3_grid_disk_distances('85283473fffffff'::h3index, 2);

-- 距离为 k 的空心六边形环
SELECT h3_grid_ring_unsafe('85283473fffffff'::h3index, 1);

-- 两个单元格之间的索引路径(含端点)
SELECT h3_grid_path_cells('85283473fffffff'::h3index, '8528342bfffffff'::h3index);

-- 两个索引之间的网格距离
SELECT h3_grid_distance('85283473fffffff'::h3index, '8528342bfffffff'::h3index);

-- 局部 IJ 坐标
SELECT h3_cell_to_local_ij('85283473fffffff'::h3index, '8528342bfffffff'::h3index);
SELECT h3_local_ij_to_cell('85283473fffffff'::h3index, POINT(0,0));

层次网格函数

在 H3 网格系统中的不同分辨率之间移动,生成父级(更粗)或子级(更细)单元格。

-- 获取更粗分辨率的父单元格
SELECT h3_cell_to_parent('85283473fffffff'::h3index, 3);

-- 获取更细分辨率的所有子单元格
SELECT h3_cell_to_children('85283473fffffff'::h3index, 7);

-- 获取更细分辨率的中心子单元格
SELECT h3_cell_to_center_child('85283473fffffff'::h3index, 7);

-- 压缩单元格数组
SELECT h3_compact_cells(ARRAY['85283473fffffff'::h3index, '85283477fffffff'::h3index]);

-- 解压到目标分辨率
SELECT h3_uncompact_cells(ARRAY['85283473fffffff'::h3index], 7);

-- 获取子单元格在父单元格子列表中的位置
SELECT h3_cell_to_child_pos('872834700ffffff'::h3index, 5);

-- 获取指定位置的子单元格
SELECT h3_child_pos_to_cell(0, '85283473fffffff'::h3index, 7);

区域函数

在 H3 索引和多边形区域之间互转。

-- 用指定分辨率的六边形填充多边形
SELECT h3_polygon_to_cells(
    '((37.7,-122.5),(37.8,-122.5),(37.8,-122.4),(37.7,-122.4))'::polygon,
    NULL::polygon[],
    5
);

-- 获取一组六边形的轮廓多边形
SELECT * FROM h3_cells_to_multi_polygon(
    ARRAY['85283473fffffff'::h3index, '85283477fffffff'::h3index]
);

单向边函数

编码从一个单元格到相邻单元格的有向边。

-- 检查两个单元格是否相邻
SELECT h3_are_neighbor_cells('85283473fffffff'::h3index, '85283477fffffff'::h3index);

-- 获取相邻单元格之间的有向边
SELECT h3_cells_to_directed_edge('85283473fffffff'::h3index, '85283477fffffff'::h3index);

-- 验证边
SELECT h3_is_valid_directed_edge(edge) FROM ...;

-- 从边获取起点和终点
SELECT h3_get_directed_edge_origin(edge);
SELECT h3_get_directed_edge_destination(edge);

-- 以记录形式获取两端
SELECT * FROM h3_directed_edge_to_cells(edge);

-- 从一个单元格出发的所有边
SELECT h3_origin_to_directed_edges('85283473fffffff'::h3index);

-- 边界坐标
SELECT h3_directed_edge_to_boundary(edge);

顶点函数

-- 获取单元格的单个顶点
SELECT h3_cell_to_vertex('85283473fffffff'::h3index, 0);

-- 获取单元格的所有顶点
SELECT h3_cell_to_vertexes('85283473fffffff'::h3index);

-- 获取顶点的地理坐标
SELECT h3_vertex_to_latlng(vertex);

-- 验证顶点
SELECT h3_is_valid_vertex(vertex);

杂项函数

-- 两点之间的大圆距离(km、m 或 rads)
SELECT h3_great_circle_distance(POINT(37.7,-122.5), POINT(40.7,-74.0), 'km');

-- 指定分辨率的六边形平均面积
SELECT h3_get_hexagon_area_avg(5, 'km^2');

-- 特定单元格的精确面积
SELECT h3_cell_area('85283473fffffff'::h3index, 'km^2');

-- 指定分辨率的平均边长
SELECT h3_get_hexagon_edge_length_avg(5, 'km');

-- 精确边长
SELECT h3_edge_length(edge, 'km');

-- 指定分辨率的唯一单元格数
SELECT h3_get_num_cells(5);

-- 全部 122 个分辨率 0 的单元格
SELECT h3_get_res_0_cells();

-- 指定分辨率的所有五边形
SELECT h3_get_pentagons(5);

运算符

-- 网格距离运算符
SELECT '85283473fffffff'::h3index <-> '8528342bfffffff'::h3index;

-- B-tree 等于/不等于
SELECT a = b, a <> b FROM ...;

-- R-tree 空间运算符
SELECT a && b  -- 相交
SELECT a @> b  -- 包含
SELECT a <@ b  -- 被包含

SP-GiST 索引(实验性)

CREATE INDEX spgist_idx ON h3_data USING spgist(hex h3index_ops_experimental);

类型转换

-- H3 索引与 bigint 互转
SELECT '85283473fffffff'::h3index::bigint;
SELECT 599686042433355775::bigint::h3index;

-- H3 索引转 point
SELECT '85283473fffffff'::h3index::point;

PostGIS 集成

传递给 h3-pg PostGIS 函数的 GEOMETRY 数据应使用 SRID 4326。使用其他 SRID(如 3857)可能导致错误或无效数据。

PostGIS 集成需要伴随扩展 h3_postgis

CREATE EXTENSION h3_postgis CASCADE;

-- 对 PostGIS 几何体建立指定分辨率的索引
SELECT h3_latlng_to_cell(geom, 9) FROM points;

-- 将 H3 单元格转换为 PostGIS geometry/geography
SELECT h3_cell_to_geometry('85283473fffffff'::h3index);
SELECT h3_cell_to_geography('85283473fffffff'::h3index);

-- 单元格边界转 PostGIS 几何体(在反子午线处分割)
SELECT h3_cell_to_boundary_geometry('85283473fffffff'::h3index);

-- 用 H3 单元格填充 PostGIS 多边形
SELECT h3_polygon_to_cells(geom, 7) FROM polygons;

-- 将 H3 单元格转回 PostGIS 多多边形
SELECT h3_cells_to_multi_polygon_geometry(ARRAY['85283473fffffff'::h3index]);

-- PostGIS 索引运算符
SELECT geom @ 9 FROM points;  -- geometry @ resolution

栅格处理

对于连续栅格数据(温度、高程等),汇总 H3 单元格内的像素值:

SELECT
    (summary).h3 AS h3,
    (h3_raster_summary_stats_agg((summary).stats)).*
FROM (
    SELECT h3_raster_summary(rast, 8) AS summary
    FROM rasters
) t
GROUP BY 1;

对于离散/分类栅格数据(土地覆盖、土地利用),按 H3 单元格聚合分类统计:

SELECT
    h3,
    jsonb_object_agg(
        concat('class_', val::text),
        h3_raster_class_summary_item_to_jsonb(item)
        ORDER BY val
    ) AS summary
FROM (
    SELECT h3, val, h3_raster_class_summary_item_agg(summary) AS item
    FROM rasters, h3_raster_class_summary(rast, 8)
    GROUP BY 1, 2
) t
GROUP BY 1;

栅格汇总方法:h3_raster_summary(自动选择)、h3_raster_summary_clip(按单元格几何体裁剪)、h3_raster_summary_centroids(按像素质心分组)、h3_raster_summary_subpixel(适用于亚像素 H3 单元格)。分类汇总也有相同的变体。


最后修改 2026-03-21: routine extension update (0532370)