golang实现地理空间六边形层级索引系统插件库H3的使用

Golang实现地理空间六边形层级索引系统插件库H3的使用

H3 Logo

H3-Go是H3核心库的Golang绑定,用于地理空间六边形层级索引系统。

安装

go get github.com/uber/h3-go/v4

快速开始示例

import "github.com/uber/h3-go/v4"

func ExampleLatLngToCell() {
    // 创建经纬度点
    latLng := h3.NewLatLng(37.775938728915946, -122.41795063018799)
    // 设置分辨率(0-15,0为最大单元格,15为最小单元格)
    resolution := 9 

    // 将经纬度转换为H3单元格
    cell := h3.LatLngToCell(latLng, resolution)

    fmt.Printf("%s", cell)
    // 输出:
    // 8928308280fffff
}

主要功能示例

1. 经纬度与H3单元格互转

// 经纬度转H3单元格
latLng := h3.NewLatLng(37.775938728915946, -122.41795063018799)
cell := h3.LatLngToCell(latLng, 9)

// H3单元格转经纬度
center := cell.LatLng()
fmt.Println(center.Lat, center.Lng)

2. 获取单元格边界

// 获取H3单元格的边界坐标
boundary := cell.Boundary()
for _, coord := range boundary {
    fmt.Printf("(%f, %f)\n", coord.Lat, coord.Lng)
}

3. 网格盘操作

// 获取中心单元格周围的网格盘
cells := cell.GridDisk(2) // 2环范围内的所有单元格
for _, neighbor := range cells {
    fmt.Println(neighbor)
}

// 带距离的网格盘
cells, distances := cell.GridDiskDistances(2)
for i, neighbor := range cells {
    fmt.Printf("Cell: %s, Distance: %d\n", neighbor, distances[i])
}

4. 单元格层级关系

// 获取父单元格
parent := cell.Parent(8) // 获取分辨率8的父单元格

// 获取子单元格
children := cell.Children(10) // 获取分辨率10的所有子单元格

// 获取中心子单元格
centerChild := cell.CenterChild(10)

5. 多边形填充

// 定义多边形
polygon := h3.GeoPolygon{
    GeoLoop: h3.GeoLoop{
        // 多边形顶点坐标
        {Lat: 37.813318999983238, Lng: -122.4089866999972145},
        {Lat: 37.7866302000007224, Lng: -122.3805436999997056},
        {Lat: 37.7198061999978478, Lng: -122.3544736999993603},
        {Lat: 37.7076131999975672, Lng: -122.5123436999983966},
        {Lat: 37.7835871999971715, Lng: -122.5247187000021967},
    },
    // 孔洞(可选)
    Holes: []h3.GeoLoop{},
}

// 将多边形填充为H3单元格
resolution := 9
cells := polygon.Cells(resolution)
for _, cell := range cells {
    fmt.Println(cell)
}

C API绑定对照表

C API Go API
latLngToCell LatLngToCell, LatLng#Cell
cellToLatLng CellToLatLng, Cell#LatLng
cellToBoundary CellToBoundary, Cell#Boundary
gridDisk GridDisk, Cell#GridDisk
gridDistance GridDistance, Cell#GridDistance
polygonToCells PolygonToCells, GeoPolygon#Cells
cellsToMultiPolygon CellsToMultiPolygon
cellToParent Cell#Parent, Cell#ImmediateParent
cellToChildren Cell#Children, Cell#ImmediateChildren

注意事项

  1. H3-Go需要启用CGO (CGO_ENABLED=1)才能编译
  2. LatLng返回的LatLng是以度为单位,而不是弧度
  3. H3 C API中的get前缀在Go绑定中被去掉了,遵循Go的命名风格
  4. 为各种类型添加了便捷方法,其中该类型是主要或唯一参数

H3-Go使用Apache 2.0许可证,欢迎提交Pull Request和Github问题。


更多关于golang实现地理空间六边形层级索引系统插件库H3的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang实现地理空间六边形层级索引系统插件库H3的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang实现地理空间六边形层级索引系统H3的使用

H3是Uber开源的地理空间索引系统,它将地球表面划分为六边形的网格,提供高效的地理空间索引和查询功能。下面介绍如何在Golang中使用H3库。

安装H3 Go绑定

首先安装H3的Go绑定:

go get github.com/uber/h3-go/v3

基本使用示例

1. 经纬度坐标转H3索引

package main

import (
	"fmt"
	"github.com/uber/h3-go/v3"
)

func main() {
	// 定义经纬度坐标(纽约市)
	lat, lng := 40.7128, -74.0060
	
	// 设置H3分辨率(0-15, 0最粗糙, 15最精细)
	resolution := 9
	
	// 将经纬度转换为H3索引
	index := h3.FromGeo(h3.GeoCoord{
		Latitude:  lat,
		Longitude: lng,
	}, resolution)
	
	fmt.Printf("H3索引: %x\n", index)
	fmt.Printf("H3索引字符串: %s\n", h3.ToString(index))
}

2. H3索引转回经纬度

func h3ToGeo() {
	// 从字符串解析H3索引
	index, err := h3.FromString("892a100acc7ffff")
	if err != nil {
		panic(err)
	}
	
	// 获取六边形的中心点坐标
	center := h3.ToGeo(index)
	fmt.Printf("中心点坐标: 纬度 %.6f, 经度 %.6f\n", center.Latitude, center.Longitude)
	
	// 获取六边形的边界坐标
	boundary := h3.ToGeoBoundary(index)
	fmt.Println("六边形边界坐标:")
	for _, coord := range boundary {
		fmt.Printf("纬度 %.6f, 经度 %.6f\n", coord.Latitude, coord.Longitude)
	}
}

3. 六边形邻居和层级操作

func neighborsAndHierarchy() {
	index, _ := h3.FromString("892a100acc7ffff")
	
	// 获取所有邻居六边形
	neighbors := h3.KRing(index, 1)
	fmt.Printf("邻居六边形数量: %d\n", len(neighbors))
	
	// 获取父级六边形(低一级分辨率)
	parent := h3.ToParent(index, 8)
	fmt.Printf("父级H3索引: %s\n", h3.ToString(parent))
	
	// 获取子级六边形(高一级分辨率)
	children := h3.ToChildren(index, 10)
	fmt.Printf("子级六边形数量: %d\n", len(children))
}

4. 区域填充和距离计算

func areaAndDistance() {
	// 定义两个坐标点
	coord1 := h3.GeoCoord{Latitude: 40.7128, Longitude: -74.0060} // 纽约
	coord2 := h3.GeoCoord{Latitude: 34.0522, Longitude: -118.2437} // 洛杉矶
	
	// 计算两点间的H3距离
	index1 := h3.FromGeo(coord1, 9)
	index2 := h3.FromGeo(coord2, 9)
	distance := h3.Distance(index1, index2)
	fmt.Printf("H3网格距离: %d\n", distance)
	
	// 计算六边形面积(km²)
	area := h3.CellArea(index1, h3.Km2)
	fmt.Printf("六边形面积: %.2f km²\n", area)
	
	// 多边形填充示例
	polygon := h3.GeoBoundary{
		{Latitude: 40.7128, Longitude: -74.0060},
		{Latitude: 40.7218, Longitude: -74.0060},
		{Latitude: 40.7218, Longitude: -73.9970},
		{Latitude: 40.7128, Longitude: -73.9970},
	}
	filled := h3.Polyfill(polygon, 9)
	fmt.Printf("多边形填充的六边形数量: %d\n", len(filled))
}

实际应用场景

  1. 地理围栏:快速判断点是否在某个区域内
  2. 邻近搜索:查找附近的点或区域
  3. 空间聚合:将数据聚合到不同分辨率的六边形中
  4. 路径规划:计算网格间的距离和路径

性能优化建议

  1. 根据需求选择合适的分辨率,分辨率越高,索引越多,计算量越大
  2. 对于大量数据,考虑使用H3索引作为数据库索引
  3. 批量处理H3操作比单次操作更高效

完整示例

package main

import (
	"fmt"
	"github.com/uber/h3-go/v3"
)

func main() {
	// 示例坐标(旧金山金门大桥)
	lat, lng := 37.8199, -122.4783
	resolution := 10
	
	// 1. 经纬度转H3
	index := h3.FromGeo(h3.GeoCoord{
		Latitude:  lat,
		Longitude: lng,
	}, resolution)
	fmt.Printf("金门大桥H3索引: %s\n", h3.ToString(index))
	
	// 2. 获取邻居
	neighbors := h3.KRing(index, 2)
	fmt.Printf("2环邻居数量: %d\n", len(neighbors))
	
	// 3. 计算面积
	areaKm2 := h3.CellArea(index, h3.Km2)
	areaM2 := h3.CellArea(index, h3.M2)
	fmt.Printf("六边形面积: %.6f km² / %.2f m²\n", areaKm2, areaM2)
	
	// 4. 分辨率转换
	fmt.Println("\n不同分辨率下的同一位置:")
	for res := 15; res >= 0; res -= 3 {
		idx := h3.FromGeo(h3.GeoCoord{Latitude: lat, Longitude: lng}, res)
		area := h3.CellArea(idx, h3.Km2)
		fmt.Printf("Res %2d: %-15s (%.4f km²)\n", res, h3.ToString(idx), area)
	}
}

H3库为地理空间分析提供了强大的工具,特别适合需要高效地理索引和查询的应用场景。通过合理选择分辨率和利用H3的层次结构,可以实现高性能的地理空间计算。

回到顶部