Uber H3 index 地图索引思考
H3 是 uber 设计的六边形空间索引,go 语言操作包是 h3-go,可以通过经纬度获取所在的 h3 六边形边界,每个经纬度对应的六边形都是确定的,每个六边形唯一对应了一个 h3index。在业务开发中,我们可以通过 h3index 来对地理空间中的对象做聚合,本质还是将经纬度查询转换成了 h3index 的查询。
维度
不同维度的 h3index 表示不同大小的地理空间,我们可以查看官方介绍来了解对应关系。h3 有 16 个维度,维度越高,表示的面积越小,也就越是精确。下图的对应关系,表示不同维度的h3index 表示地球的组成。
拿维度 15 来说,已经是 h3 能表示的最小单元了。用这个维度来表示地球的话,需要存储 569,707,381,193,162 个该维度的 h3index 索引。后面又列举了其中六边形(hexagon)和五边形(pentagon)的组成个数。为什么组成中还会有五变形呢? 我们应该从设计的根源上去探索解释。

使用 h3-go 包,我们通过指定经纬度、以及维度就可以获取到对应的 h3index 索引。还可以通过 h3index 获取所在六边形的组成点。下面代码中 FromGeo 就返回了对应的 h3index。
geo := GeoCoord{Latitude: 37.775938728915946,Longitude: -122.41795063018799,
}
resolution := 9
fmt.Printf("%#x\n", FromGeo(geo, resolution))
想比较 h3index 能表示的最小单元格个数而言,我们最关心的还是单元格所能表示的面积大小,不同维度的 h3index 究竟能表示多大的范围。
H3 设计
将真实世界的 3 维地理空间映射到 2 维的网格体系,是每个地图索引都需要面对的问题。H3 通过球心投影的方式将地球抽象成一个空间正20 面体,但地球本身也不是极致的圆形,抽象肯定会牺牲一部分准确性。
正20面体的每个面都是一个三角形平面,抽象到地图上的话,每个平面应该都是二维的平面。然后就变成了一个圆形的正20面体,就正好可以接受地图的投影。而且,如果把正 20 面体的每个面进行编码,我们可以通过选择正 20 面体,将合适的面对应到合适的地理区域上。

正 20 面体展开到二维平面,就是地球的投影,下面就是其中的一种展开方式。因为有陆地和海洋的区别,而我们要分析的地理数据基本都是在陆地上的。所以,正 20 面体通过合理的转动,可以将它的顶点都落在海洋的区域。为什么要特别处理这些顶点数据呢?

H3网格索引没有直接利用正 20 面体,而是在每个面的基础上继续做了网格拆分。为什么最终选择使用正六边形作为拆分的单元呢,还有没有别的多边形可以选择呢?其实还可以有三角形和正方形,GeoHash 采用的就是正方面的网格,那么正方形网格和正六边形有什么区别吗?
假设一个 n 面体,多面体的内角和计算公式为 (n-2)*180,假设 m 个正多边形在任意顶点出拼接形成一个 360 度才能形成网格,最终计算的表达式:(n-2)*180/n*m=360。如果 n 表示三角形,就需要有 6 个面拼接;如果 n 是正方形,就需要 4 个面拼接,如果 n 是六边形,就需要 3 个面拼接。

如果按照三角形或者四边形的拆分方式,某一个网格单元和临边的网格单元的中心距离是不相同的,如上图。但采用正六边形,网格单元和临边的其它网格单元是相同的。那么,在网格体系中,我们如何获取某个网格单元周边的网格呢?
H3 网格独立于现实中的区域,真实世界的区域边界往往会发生一些变化,区域的边界形态各异,经常还会发生变动调整,如果保持现实地理的区域跟踪,保证区域边界数据动态更新难度可想而知。试想一下,如果我们根据北京的每个区、每个街道进行数据统计,复杂性是非常大的。
而 H3 是在地球基础上的网格系统,它不用关心现实的街道、区域边界变化,无论现实中的地域如何变化,H3 都不会发生变化,也就是将地图上的某一个区域固定化了。如果要统计某个区域的维度信息,只需要先获取该区域的所有 H3 网格,汇总所有网格的信息就可以了。


在 0 级索引下,每个面包含了 10 个单元,如上图,其中边界线上的一些单元会被多个平面共同包含,这个面总共包含了 5.5 个六边形和 3 个三角形。上文提到的,正20面体所包含的 110 个六边形和 12 个五边形就是这么计算的出来的。正20面体包含有 20 个面、30条边、12 个顶点,其中的 12 个顶点就正好对应了这 12 个五边形。

上图形象的描述了,2个等级 H3 网格的大小关系,高级别的 H3 网格大概需要 7 个接近一个低级别的网格,两个级别之间不是完全的包含关系。
参考文章:
- Uber’s Hexagonal Hierarchical Spatial Index
- h3geo文档
相关文章:
Uber H3 index 地图索引思考
H3 是 uber 设计的六边形空间索引,go 语言操作包是 h3-go,可以通过经纬度获取所在的 h3 六边形边界,每个经纬度对应的六边形都是确定的,每个六边形唯一对应了一个 h3index。在业务开发中,我们可以通过 h3index 来对地理…...
多线程的几种状态
Java-多线程的几种状态🔎1.NEW( 系统中线程还未创建,只是有个Thread对象)🔎2.RUNNABLE( (就绪状态. 又可以分成正在工作中和即将开始工作)🔎3.TERMINATED(系统中的线程已经执行完了,Thread对象还在)🔎4.TIMED_WAITING(指定时间等待…...
【算法题】1574. 删除最短的子数组使剩余数组有序
题目: 给你一个整数数组 arr ,请你删除一个子数组(可以为空),使得 arr 中剩下的元素是 非递减 的。 一个子数组指的是原数组中连续的一个子序列。 请你返回满足题目要求的最短子数组的长度。 示例 1: …...
理解对数——金融问题中的自然对数(以e为底的对数)
第3章 金融问题(Financial Matters)——金融问题中的自然对数If thou lend moneyto any ofMy people. ...thou shalt not beto him as a creditor;neither shall yelay upon him interest.(如果你借钱给我的任何人。 ……你不应该是他的债权人;也不可向他加息。)——…...
vue2进阶学习之路
HTML、CSS和JavaScript基础 在学习Vue2之前,需要掌握HTML、CSS和JavaScript的基础知识。包括HTML的标签、CSS的布局和样式、JavaScript的变量类型、条件语句、循环语句等。 Vue2的基础知识 掌握Vue2的基本概念和语法,包括Vue2实例、数据绑定、指令、组件…...
决策树ID3算法
1. 决策树ID3算法的信息论基础 机器学习算法其实很古老,作为一个码农经常会不停的敲if, else if, else,其实就已经在用到决策树的思想了。只是你有没有想过,有这么多条件,用哪个条件特征先做if,哪个条件特征后做if比较优呢&#…...
C++模板基础(一)
函数模板(一) ● 使用 template 关键字引入模板: template void fun(T) {…} – 函数模板的声明与定义 – typename 关键字可以替换为 class ,含义相同 – 函数模板中包含了两对参数:函数形参 / 实参;模板形…...
生产者消费者模型线程池(纯代码)
目录 生产者消费者模型 条件变量&&互斥锁(阻塞队列) makefile Task.hpp BlockQueue.hpp BlockQueueTest.cc 信号量&&互斥锁(环形队列) makefile RingQueue.hpp RingQueueTest.cc 线程池(封…...
K8s 应用的网络可观测性: Cilium VS DeepFlow
随着分布式服务架构的流行,特别是微服务等设计理念在现代应用普及开来,应用中的服务变得越来越分散,因此服务之间的通信变得越来越依赖网络,很有必要来谈谈实现微服务可观测性中越来越重要的一环——云原生网络的可观测。K8s 是微服务设计理念能落地的最重要的承载体,本文…...
3.29面试题
文章目录内存内存管理执行过程要点面试题内存 内存管理 由JVM管理 堆:new出来的对象(包括成员变量、数组元素、方法的地址)栈:局部变量(包括方法的参数)方法区:.class字节码文件(…...
操作系统漏洞发现
操作系统漏洞发现前言一、操作系统漏洞发现1.1 namp2. Goby3. Nessus二,进行渗透测试2.1 使用工具进行渗透1. metasploit2.2 EXP2.3 复现文章三,操作系统漏洞修复前言 不管是对于App来说,还是web站点来说,操作系统是必须的&#x…...
Linux gdb调试底层原理
TOC 前言 linux下gdb调试程序操作过程参考本人文章:gdb调试操作; 这里不再叙述; 本文主要内容是介绍GDB本地调试的底层调试原理,我们来看一下GDB是通过什么机制来控制被调试程序的执行顺序; 总结部分是断点调试的底层原理,可以直接跳转过去先看看大概…...
LC-1647. 字符频次唯一的最小删除次数(哈希+计数)
1647. 字符频次唯一的最小删除次数 难度中等56 如果字符串 s 中 不存在 两个不同字符 频次 相同的情况,就称 s 是 优质字符串 。 给你一个字符串 s,返回使 s 成为 优质字符串 需要删除的 最小 字符数。 字符串中字符的 频次 是该字符在字符串中的出现…...
HTTP状态码
100: 接受,正在继续处理 200: 请求成功,并返回数据 201: 请求已创建 202: 请求已接受 203: 请求成为,但未授权 204: 请求成功,没有内容 205: 请求成功,重置内容 206: 请求成功,返回部分内容 301: 永久性重定…...
【Linux】初见“which命令”,“find命令”以及linux执行命令优先级
文章目录1.which命令1.1 whereis命令1.2 locate命令1.3 搜索文件命令总结2.find命令2.1 find之exec用法2.2 管道符之xargs用法3 Linux常用命令4.命令执行优先级1.which命令 查找命令文件存放目录 搜索范围由环境变量PATH决定(echo $PATH) which命令格式࿱…...
update case when 多字段,多条件, mysql中case when用法
文章目录 前言 sql示例 普通写法: update case when写法 update case when 多字段写法 case when语法 case when 的坑 1、不符合case when条件但是字段被更新为null了 解决方法一:添加where条件 解决方法二:添加else 原样输出 2、同一条数据符…...
mysql隐式转换 “undefined“字符串匹配到mysql int类型0值字段
描述:mysql 用字符串搜索 能搜到int类型查询结果 mysql int类型条件用字符串查询 table: CREATE TABLE all_participate_records (id bigint unsigned NOT NULL AUTO_INCREMENT,created_at datetime(3) DEFAULT NULL,updated_at datetime(3) DEFAULT NULL,deleted…...
Redis八股文
1.Redis是什么? Redis 是一个基于 C 语言开发的开源数据库(BSD 许可),与传统数据库不同的是 Redis 的数据是存在内存中的(内存数据库),读写速度非常快,被广泛应用于缓存方向。并且,…...
InnoDB——详细解释锁的应用,一致性读,自增长与外键
一致性非锁定读 一致性的非锁定读(consistent nonlocking read)是指InnoDB存储引擎通过行多版本控制的方式读取当前执行时数据库中行的数据。 如果读取的行正在执行 行Delete或Update操作,这时读取操作不会因此去等待行上锁的释放。相反&…...
C++模板基础(四)
函数模板(四) ● 函数模板的实例化控制 – 显式实例化定义: template void fun(int) / template void fun(int) //header.h template<typename T> void fun(T x) {std::cout << x << std::endl; }//main.cpp #include&quo…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...
Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...
MySQL用户和授权
开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务: test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
腾讯云V3签名
想要接入腾讯云的Api,必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口,但总是卡在签名这一步,最后放弃选择SDK,这次终于自己代码实现。 可能腾讯云翻新了接口文档,现在阅读起来,清晰了很多&…...
React从基础入门到高级实战:React 实战项目 - 项目五:微前端与模块化架构
React 实战项目:微前端与模块化架构 欢迎来到 React 开发教程专栏 的第 30 篇!在前 29 篇文章中,我们从 React 的基础概念逐步深入到高级技巧,涵盖了组件设计、状态管理、路由配置、性能优化和企业级应用等核心内容。这一次&…...
