python 之 h3 六边形分层地理空间索引系统
H3的主要功能说明
H3是Uber开源的六边形层次化地理空间索引系统,主要功能包括:
-
地理空间索引
- 将地球表面划分为大小均匀的六边形网格
- 支持16个不同的分辨率级别(0-15)
- 级别0的六边形最大,级别15的六边形最小
-
坐标转换
- 将经纬度坐标转换为唯一的H3索引(六边形ID)
- 支持从H3索引反向解析为地理坐标
-
空间关系计算
- 查找相邻的六边形
- 计算六边形之间的距离
- 判断空间包含关系
-
层次化结构
- 支持不同分辨率级别之间的转换
- 可以获取父级或子级六边形
-
主要应用场景
- 地理位置聚合和分析
- 空间数据可视化
- 路径规划和导航
- 地理围栏和区域分析
- 位置服务和地理大数据处理
-
分辨率级别示例:
分辨率 边长(公里) 六边形面积(平方公里) 0 1107.71 4,250,546.847 1 418.76 607,581.625 2 158.24 86,797.375 3 59.81 12,399.625 4 22.59 1,771.375 5 8.53 253.053 6 3.22 36.15 7 1.22 5.164 8 0.46 0.738 9 0.17 0.105 10 0.06 0.015 11 0.02 0.002 12 0.01 0.0003 13 0.004 0.00004 14 0.0015 0.000006 15 0.0005 0.000001
二、基础转换函数
-
地理坐标转换为H3索引
import h3# 坐标点和H3分辨率级别 lat = 40.7128 # 纬度 - 纽约市示例纬度 lng = -74.0060 # 经度 - 纽约市示例经度 resolution = 7 # H3分辨率级别 (0-15,数值越大网格越小)# 使用现代函数名将地理坐标转换为H3索引 h3_index = h3.latlng_to_cell(lat, lng, resolution) print(f"H3索引: {h3_index}")H3 index: 872a1072cffffff -
索引反向解析为地理坐标[中心坐标]
import h3# 从H3索引反向获取经纬度坐标 h3_index = "872830828ffffff" # 示例H3索引# 将H3索引转换为经纬度坐标 lat, lng = h3.cell_to_latlng(h3_index) print(f"经纬度坐标: {lat}, {lng}")经纬度坐标: 40.72305436427269, -74.00178736299634 -
获取六边形的边界坐标
import h3 h3_index = h3.latlng_to_cell(37.775938728915946, -122.41795063018799, 10)# 获取六边形的边界坐标 boundary = h3.cell_to_boundary(h3_index)print(boundary)((37.775197782893386, -122.41719971841658), (37.775703986717936, -122.41656062678756), (37.77637424842295, -122.41676746054856), (37.77653830250715, -122.41761339284626), (37.776032096294685, -122.41825248012377), (37.775361838385955, -122.4180456394552) )
顶点
| 函数名称 | 功能描述 |
|---|---|
cell_to_vertex(h, vertex_num) | 返回H3单元h的指定顶点(vertex_num)。 |
cell_to_vertexes(h) | 返回H3单元h的所有顶点的列表。 |
vertex_to_latlng(vertex) | 返回指定顶点vertex的纬度和经度。 |
cell_to_vertex(h, vertex_num)返回顶点的纬度和经度vertices = h3.cell_to_vertexes(h3_index) print(f"所有顶点 ({len(vertices )} 个):")vertex_to_latlng(vertex)返回指定顶点vertex的纬度和经度for i, vertex in enumerate(vertices):vertex_lat, vertex_lng = h3.vertex_to_latlng(vertex) # 顶点坐标print(f" 顶点{i}: {vertex} -> ({vertex_lat:.6f}, {vertex_lng:.6f})")cell_to_vertexes(h)获取第几顶点的纬度和经度坐标vertex = h3.cell_to_vertex(h3_index, 5) print(vertex, '---------------')
边
| 函数名称 | 功能描述 |
|---|---|
cells_to_directed_edge(origin, destination) | 创建一个表示从origin到destination的单向边的H3索引。 |
directed_edge_to_cells(e) | 从H3有向边索引e中返回一个包含起点和终点的元组。 |
get_directed_edge_origin(e) | 从H3有向边索引e中获取起点单元。 |
get_directed_edge_destination(e) | 从H3有向边索引e中获取终点单元。 |
origin_to_directed_edges(origin) | 返回从origin单元开始的所有有向边。 |
-
import h3# 假设我们有两个H3索引,分别表示地点A和B[必须为邻居的点] origin = h3.latlng_to_cell(37.775938728915946, -122.41795063018799, 9) # 地点A destination = h3.latlng_to_cell(37.77351509723814, -122.4182710369247, 9) # 地点B -
cells_to_directed_edge(origin, destination)创建一个表示单向边的 H3 索引 origin -> destinationdirected_edge = h3.cells_to_directed_edge(origin, destination)14928308280fffff -
directed_edge_to_cells(e)获取有向边的起点和终点 索引origin_cell, destination_cell = h3.directed_edge_to_cells(directed_edge) print(f"起点: {origin_cell}, 终点: {destination_cell}")起点: 8928308280fffff, 终点: 89283082803ffff -
get_directed_edge_origin(e)获取有向边的起点origin_from_edge = h3.get_directed_edge_origin(directed_edge) print(f"有向边起点: {origin_from_edge}")有向边起点: 8928308280fffff# 等同于下 h3_index = h3.latlng_to_cell(37.775938728915946, -122.41795063018799, 9) -
get_directed_edge_destination(e)获取有向边的终点destination_from_edge = h3.get_directed_edge_destination(directed_edge) print(f"有向边终点: {destination_from_edge}")有向边终点: 89283082803ffff -
origin_to_directed_edges(origin)获取从起点出发的所有有向边all_directed_edges_from_origin = h3.origin_to_directed_edges(origin) print("从起点出发的所有有向边:") for edge in all_directed_edges_from_origin:print(edge)从起点出发的所有有向边: 11928308280fffff 12928308280fffff 13928308280fffff 14928308280fffff 15928308280fffff 16928308280fffff
计算的球形表面积
import h3
h3_index = h3.latlng_to_cell(37.775938728915946, -122.41795063018799, 10)
# 平方公里
area_km2 = h3.cell_area(h3_index, unit='km^2')
print(f" 平方公里 (km²): {area_km2:.6f} km²")
# 平方米
area_m2 = h3.cell_area(h3_index, unit='m^2')
print(f" 平方米 (m²): {area_m2:.2f} m²")
# 球面弧度平方
area_rads2 = h3.cell_area(h3_index, unit='rads^2')
print(f" 球面弧度平方 (rads²): {area_rads2:.10f} rads²")
# 验证单位转换
earth_radius_km = 6371.0088 # 地球平均半径
expected_km2 = area_rads2 * (earth_radius_km ** 2)print(f" rads² × R_earth² = {expected_km2:.6f} km²")
print(f" 与实际km²值的差异: {abs(expected_km2 - area_km2):.10f} km²")
