高效的多维空间点索引算法——GeoHash

一、Geohash 算法简介

    GeoHash是空间索引的一种方式,其基本原理是将地球理解为一个二维平面,通过把二维的空间经纬度数据编码为一个字符串,可以把平面递归分解成更小的子块,每个子块在一定经纬度范围内拥有相同的编码。以GeoHash方式建立空间索引,可以提高对空间poi数据进行经纬度检索的效率。Geohash 属于空间填充曲线中的 Z 阶曲线(Z-order curve)的实际应用。

    Geohash是一种地址编码,它能把二维的经纬度编码成一维的字符串,Geohash 就常常被用来作为唯一标识符。用在数据库里面可用 Geohash 来表示一个点。Geohash 这个公共前缀的特性就可以用来快速的进行邻近点的搜索。越接近的点通常和目标点的 Geohash 字符串公共前缀越长

1.Z曲线

上图就是 Z 阶曲线。生成它只需要把每个 Z 首尾相连即可。

    Z 阶曲线同样可以扩展到三维空间。只要 Z 形状足够小并且足够密,也能填满整个三维空间。Geohash算法 的理论基础就是基于 Z 曲线的生成原理。

2.Geohash基础

    Geohash 能够提供任意精度的分段级别。一般分级从 1-12 级。

    可以利用 Geohash 的字符串长短来决定要划分区域的大小。这个对应关系可以参考上面表格里面 cell 的宽和高。一旦选定 cell 的宽和高,那么 Geohash 字符串的长度就确定下来了。这样我们就把地图分成了一个个的矩形区域了。

    地图上虽然把区域划分好了,但是还有一个问题没有解决,那就是如何快速的查找一个点附近邻近的点和区域呢?

    Geohash 有一个和 Z 阶曲线相关的性质,那就是一个点附近的地方(但不绝对) hash 字符串总是有公共前缀,并且公共前缀的长度越长,这两个点距离越近。

    由于这个特性,Geohash 就常常被用来作为唯一标识符。用在数据库里面可用 Geohash 来表示一个点。Geohash 这个公共前缀的特性就可以用来快速的进行邻近点的搜索。越接近的点通常和目标点的 Geohash 字符串公共前缀越长(但是这不一定,也有特殊情况,下面举例会说明)

3.Geohash 编码形式——base 32 和 base 36

①base 32 (十进制与字符对应关系)

②base 36

    base 36 的版本对大小写敏感,用了36个字符,“23456789bBCdDFgGhHjJKlLMnNPqQrRtTVWX”。

二、Geohash 实际应用举例

    以 base-32 为例。举个例子。假设需要查询距离美罗城最近的餐馆,该如何查询?

1.地图网格化编码规则

    利用 geohash。通过查表,我们选取字符串长度为6的矩形来网格化这张地图。经过查询,美罗城的经纬度是[31.1932993, 121.43960190000007]。

①将经纬度转换为二进制

    先处理纬度。地球的纬度区间是[-90,90]。把这个区间分为2部分,即[-90,0),[0,90]。31.1932993位于(0,90]区间,即右区间,标记为1。然后继续把(0,90]区间二分,分为[0,45),[45,90],31.1932993位于[0,45)区间,即左区间,标记为0。一直划分下去。

再处理经度,一样的处理方式。地球经度区间是[-180,180]

②将经纬度的二进制编码合并

    纬度产生的二进制是101011000101110,经度产生的二进制是110101100101101,按照偶数位放经度,奇数位放纬度的规则,重新组合经度和纬度的二进制串,生成新的:111001100111100000110011110110

③将合并后的二进制数做Base32编码

    最后一步就是把这个最终的字符串转换成字符,对应需要查找 base-32 的表。11100 11001 11100 00011 00111 10110转换成十进制是 28 25 28 3 7 22,查表编码得到最终结果,wtw37q。

我们还可以把这个网格周围8个各自都计算出来。

从地图上可以看出,这邻近的9个格子,前缀都完全一致。都是wtw37。可以看到中间大格子的 Geohash 的值是 wtw37q,那么它里面的所有小格子前缀都是 wtw37q。可以想象,当 Geohash 字符串长度为5的时候,Geohash 肯定就为 wtw37 了。

位于格子边界两侧的两点,虽然十分接近,但编码会完全不同。实际应用中,可以同时搜索当前格子周围的8个格子,即可解决这个问题。

2.Geohash和Z曲线的关系

    x 轴就是纬度,y轴就是经度。经度放偶数位,纬度放奇数位就是这样而来的。

3.精度问题

    如果递归的次数越大,则生成的二进制编码越长,因此生成的geohash编码越长,位置越精确。

4.Geohash的意义

    GeoHash用一个字符串表示经度和纬度两个坐标, 比直接用经纬度的高效很多,而且使用者可以发布地址编码,既能表明自己位于某位置附近,又不至于暴露自己的精确坐标,有助于隐私保护。

    编码过程中,通过二分范围匹配的方式来决定某个经纬坐标是编码为1还是0,因此某些邻近坐标的编码是相同的,因此GeoHash表示的并不是一个点,而是一个矩形区域。GeoHash编码的前缀可以表示更大的区域。例如wm3vzg,它的前缀wm3vz表示包含编码wm3vzg在内的更大范围。这个特性可以用于附近地点搜索。

    如果把某个区域或整个地图上的地理位置都按照Geohash编码,则会得到一个网格,编码递归粒度越细,网格的矩形区域越小,geohash编码的长度越大,则Geohash编码越精确。

5.邻近网格位置推算

    根据Geohash的编码规则将经纬度分解到二进制,结合地理常识,中心网格在南北(上下)方向上体现为纬度的变化,往北则维度的二进制加1,往南则维度的二进制减1,在东西(左右)方向上体现为经度的变化,往东则经度的二进制加1,往西则减1,可以计算出上下左右四个网格经纬度的二进制编码,再将加减得出的经纬度两两组合,计算出左上、左下、右上和右下四个网格的经纬度二进制编码,从而就可以根据Geohash的编码规则计算出周围八个网格的字符串。

三、Geohash 的优缺点

    Geohash 的优点很明显,它利用 Z 阶曲线进行编码。而 Z 阶曲线可以将二维或者多维空间里的所有点都转换成一维曲线。在数学上成为分形维。并且 Z 阶曲线还具有局部保序性。

    Z 阶曲线通过交织点的坐标值的二进制表示来简单地计算多维度中的点的z值。一旦将数据被加到该排序中,任何一维数据结构,例如二叉搜索树,B树,跳跃表或(具有低有效位被截断)哈希表 都可以用来处理数据。通过 Z 阶曲线所得到的顺序可以等同地被描述为从四叉树的深度优先遍历得到的顺序。

这也是 Geohash 的另外一个优点,搜索查找邻近点比较快。

Geohash 的缺点之一也来自 Z 阶曲线。Z 阶曲线有一个比较严重的问题,虽然有局部保序性,但是它也有突变性。在每个 Z 字母的拐角,都有可能出现顺序的突变。

    看上图中标注出来的蓝色的点点。每两个点虽然是相邻的,但是距离相隔很远。看右下角的图,两个数值邻近红色的点两者距离几乎达到了整个正方形的边长。两个数值邻近绿色的点也达到了正方形的一半的长度。

Geohash 的另外一个缺点是,如果选择不好合适的网格大小,判断邻近点可能会比较麻烦。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/208120.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

springboot 极简案例

安装idea File -> New Project 选择依赖 创建controller文件 输入controller类名 输入代码 运行项目 访问 localhost:8080/hello/boot package com.example.demo;import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.…

数据库对象介绍与实践:视图、函数、存储过程、触发器和物化视图

文章目录 一、视图(View)1、概念2、基本操作1)创建视图2)修改视图3)删除视图4)使用视图 3、使用场景4、实践 二、函数(Function)1、概念2、基本操作1)创建函数2&#xff…

粤能环保亮相迪拜COP28,智能技术铸就运河城市可持续未来

在全球应对气候变化的重要会议——迪拜COP28大会上,运河城市面临的独特环境挑战引起了广泛关注。随着城市化进程的加快,运河城市在处理固体废物、减少温室气体排放以及维持水资源安全方面面临着严峻考验。智能垃圾分类作为应对这些挑战的有效途径&#x…

一些系统日常运维命令和语句

一、前言 记录一些日常系统运维的命令和语句 二、linux命令与语句 1、linux查看各目录使用磁盘情况 du -h /home home为目录 du -h /home 2.查看内存使用情况 free -h 3、查看进程和CPU使用情况 top top 三、数据库语句 1、统计mysql数据库表数量 SELECT COUNT(*) A…

被动副业机赚钱项目教程,Docker一键安装教程

被动副业机赚钱项目教程,Docker一键安装教程 Docker一键运行 软件下载 视频教程 /opt/wxedge_storage 路径换成你设备里面的路径即可,其余参数不用变, 镜像名为onething1/wxedge 更多安装说明,可参考官方文档:容器魔…

【算法每日一练]-结构优化(保姆级教程 篇4 树状数组,线段树,分块模板篇)

目录 分块 分块算法步骤: 树状数组 树状数组步骤: 线段树点更新 点更新步骤: 线段树区间更新 区间更新步骤: 不同于倍增和前缀和与差分序列。 前缀和处理不更新的区间和 差分处理离线的区间更新问题 倍增处理离线的区间…

C++的继承语法

在面向对象编程中,继承是一种强大的机制,允许一个类(子类)从另一个类(父类)继承属性和方法。C是一种支持面向对象编程的编程语言,通过其灵活而强大的继承语法,开发者可以构建更加模块…

维普论文查重率高【详细说明】

大家好,今天来聊聊维普论文查重率高,希望能给大家提供一点参考。 以下是针对论文重复率高的情况,提供一些修改建议和技巧: 维普论文查重率高:原因分析与降重技巧 背景介绍 在学术领域,论文的重复率是衡量其…

老电脑重置后能连上WIFI但是打开360网页老是提示该网址不是私密连接

看了一下可以忽略这次提示,能够上网,但是每次打开新网页都会有“该网址不是私密连接”提示,这个提示非常大,严重影响上网。 强行下载了谷歌浏览器并打开后,提示“您的时钟慢了”,然后看了一下电脑右下角日期…

CLion手把手教你创建Windows项目

作为一个Jetbrains迷的我,下载了Jetbrains全家桶,我就想用CLion 编写 Windows 项目 前提:必须安装 Visual Studio 2022 New Project 选择 C Executable,取好项目名, 点击 Create 在 CMakeList.txt 中添加以下内容&…

系列八、SpringBoot中自定义SpringMVC配置

一、概述 作为Spring家族的明星产品,SpringBoot极大地简化了程序员的日常开发,提高了开发效率。我们很容易得借助于SpringBoot就可以快速开发业务代码。一般情况下,公司的日常开发都是基于web服务的,我们在使用idea等工具初始化一…

Zabbix补充

Zabbix的自动发现机制: Zabbix客户端主动和服务端联系,将自己的地址和端口发送服务端,来实现自动添加主机 客户端是自动的一方 缺点:自定义的网段的主机数量太多,登记耗时会很久,而且这个自动发现机制不是…

P1075 [NOIP2012 普及组] 质因数分解题解

题目 已知正整数 n 是两个不同的质数的乘积,试求出两者中较大的那个质数 输入输出格式 输入格式 输入一个正整数n 输出格式 输出一个正整数p,即较大的那个质数 输入输出样例 输入 21 输出 7 代码 //对于一个质因数,从小到大开始…

Ubuntu 22.04源码安装yasm 1.3.0

sudo lsb_release -r看到操作系统的版本是22.04,sudo uname -r可以看到内核版本是5.15.0-86-generic,sudo gcc --version可以看到版本是11.2.0,sudo make --version可以看到版本是GNU Make 4.3。 下载yasm http://yasm.tortall.net/Downlo…

扁平的MutableList元素每隔若干元素一组装入新MutableList,Kotlin

扁平的MutableList元素每隔若干元素一组装入新MutableList&#xff0c;Kotlin fun main(args: Array<String>) {val array arrayOf("a", "b", "c", "d", "e", "f", "g", "h", "i…

左值、右值 、左值引用、右值引用的总结

文章目录 什么是左值什么是右值纯右值&#xff1a;将亡值&#xff1a; 左值引用右值引用 在C语言中我们常常会提起左值(lvalue) 和 右值(rvalue) 这样的称呼。编译器在编译程序报错时&#xff0c; 有时也会报出错误信息中会包含左值、右值的说法。但是左值和右值并没有一个严谨…

Numpy数组的重塑,转置与切片 (第6讲)

Numpy数组的重塑,转置与切片 (第6讲)         🍹博主 侯小啾 感谢您的支持与信赖。☀️ 🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ�…

String 和 StringBuffer和 StringBuilder 场景应用

目录 1.三者区分2.String 不可变性的示例代码&#xff1a;3.String 频繁创建对象4.StringBuffer 是可变的&#xff0c;可以进行增删改操作而不产生新的对象。5.StringBuffer 是线程安全的&#xff0c;适合在多线程环境下使用&#xff0c;但同步会带来一定的性能损耗。 代码举例…

聚类分析 | Matlab实现基于谱聚类(Spectral Cluster)的数据聚类可视化

聚类分析 | Matlab实现基于谱聚类(Spectral Cluster)的数据聚类可视化 目录 聚类分析 | Matlab实现基于谱聚类(Spectral Cluster)的数据聚类可视化效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现基于谱聚类(Spectral Cluster)的聚类算法可视化&#xff08;完…

融云 Global IM UIKit

GlobalIM UIKit 基于多年领先的行业经验&#xff0c;我们为开发者提供功能完备的单群聊 通信能力。“分钟级”接入&#xff0c;即可得到符合海外用户使用习惯的多端同步产品。 核心功能包括&#xff1a;快速接入、功能齐全、全球化交互体验、内容审核、灵活可配置、高度自定义、…