使用geohash完成地理距离计算
geohash的原理是使用二分法,把当前的经度和纬度和最大最小的经度纬度进行无限二分,在一边则为0,否则为1,这样就可以定位
到地球上的每一个点了。然后把经度放在偶数位,纬度放在奇数位,组成一个01010101串。如果想变得更容易传输,可以用某种
方式进行hash,例如 base32
, base64
等。
下面是一个简单的实现。to_geohash
实现经度和纬度转换成010101串,similarity
比较两个01010串的前面有多少个相同的字符。
不过,to_geohash
有更高效的位运算实现,但是可读性不好,不容易懂,就不放出来了。
def to_geohash(longitude, latitude, length=30):
'''longitude 经度(在地图上竖着的线),latitude纬度(在地图上横着的线)'''
minLat, maxLat = -90.0, 90.0
minLng, maxLng = -180.0, 180.0
result = 0
for i in range(length):
if i % 2 == 0: # 偶数,设置longitude
mid = (minLng + maxLng) / 2
if longitude < mid:
result <<= 1 # push 0
maxLng = mid
else:
result = result << 1 | 1 # push 1
minLng = mid
else:
mid = (minLat + maxLat) / 2
if latitude < mid:
result <<= 1
maxLat = mid
else:
result = result << 1 | 1
minLat = mid
return str(bin(result))[2:]
def similarity(a, b):
"""比较a和b两个字符串前length位有多少位相同"""
result = 0
length = max(len(a), len(b))
a = a.ljust(length, '0')
b = b.ljust(length, '0')
for i in range(length):
if a[i] == b[i]:
result += 1
else:
break
return result
- https://www.factual.com/blog/how-geohashes-work
- http://www.bigfastblog.com/geohash-intro
- https://en.wikipedia.org/wiki/Geohash
更多文章
本站热门
- socks5 协议详解
- zerotier简明教程
- 搞定面试中的系统设计题
- 用peewee代替SQLAlchemy
- frp 源码阅读与分析(一):流程和概念
- Golang(Go语言)中实现典型的fork调用
- DNSCrypt简明教程
- 一个Gunicorn worker数量引发的血案
- Golang validator使用教程
- Docker组件介绍(一):runc和containerd
- Docker组件介绍(二):shim, docker-init和docker-proxy
- 使用Go语言实现一个异步任务框架
- 协程(coroutine)简介 - 什么是协程?
- SQLAlchemy简明教程
- Go Module 简明教程