93、Geohash算法实现

#1度约100km,故0.00001度约1米
#地球一圈40000km,4e8米,2的28次方,故均可切成28位数
#[l, mid)为左,[mid, r]为右
def lng2LngBinary(lng, levelNum = 28):
    l, r = -180, 180
    if lng < l or lng > r:
        print("lng输入值为: {}, 不在合理范围[-180, 180]内".format(lng))
        return
    lngBinary = []
    for _ in range(levelNum):
        mid = (l+r)/2
        if lng < mid:
            lngBinary.append(0)
            r = mid
        else:
            lngBinary.append(1)
            l = mid
    return lngBinary

def lngBinary2Lng(lngBinary):
    l, r = -180, 180
    for num in lngBinary:
        mid = (l+r)/2
        if num == 0:
            r = mid
        else:
            l = mid
    lng = (l+r)/2
    return lng

def lat2LatBinary(lat, levelNum = 28):
    l, r = -90, 90
    if lat < l or lat > r:
        print("lat输入值为: {}, 不在合理范围[-90, 90]内".format(lat))
        return
    latBinary = []
    for _ in range(levelNum):
        mid = (l+r)/2
        if lat < mid:
            latBinary.append(0)
            r = mid
        else:
            latBinary.append(1)
            l = mid
    return latBinary

def latBinary2Lat(latBinary):
    l, r = -90, 90
    for num in latBinary:
        mid = (l+r)/2
        if num == 0:
            r = mid
        else:
            l = mid
    lat = (l+r)/2
    return lat

#经纬度编码结合,从地址0开始,经度在偶数,纬度在奇数
def lngLatCombine(lngBinary, latBinary):
    lnglat = []
    for i in range(max(len(lngBinary), len(latBinary))):
        if i < len(lngBinary):
            lnglat.append(lngBinary[i])
        else:
            lnglat.append(0)
        if i < len(latBinary):
            lnglat.append(latBinary[i])
        else:
            lnglat.append(0)
    return lnglat

def lngLatSplit(lnglat):
    lngBinary, latBinary = [], []
    for i in range(len(lnglat)):
        if i%2 == 0:
            lngBinary.append(lnglat[i])
        else:
            latBinary.append(lnglat[i])
    return lngBinary, latBinary

#5位的二进制list转数值
def binary2Num(binary):
    num = 0
    n = len(binary)
    for i in range(n):
        num += binary[n-1-i]*pow(2,i)
    return num

def num2Binary(num):
    binary = []
    divisor = 16
    while divisor > 0:
        binary.append(num//divisor)
        num = num%divisor
        divisor = divisor//2
    return binary

def lnglat2lnglat32(lnglat):
    D = {0: '0', 1: '1', 2: '2', 3: '3', 4: '4', 5: '5', 6: '6', 7: '7', 8: '8', 9: '9',
         10: 'b', 11: 'c', 12: 'd', 13: 'e', 14: 'f', 15: 'g', 16: 'h', 17: 'j', 18: 'k', 19: 'm',
         20: 'n', 21: 'p', 22: 'q', 23: 'r', 24: 's', 25: 't', 26: 'u', 27: 'v', 28: 'w', 29: 'x',
         30: 'y', 31: 'z'}
    lnglat32 = []
    for i in range(len(lnglat)//5):
        binary = lnglat[5*i:5*(i+1)]
        num = binary2Num(binary)
        str = D[num]
        lnglat32.append(str)
    return "".join(lnglat32)

def lnglat322lnglat(lnglat32):
    D = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9,
         'b': 10, 'c': 11, 'd': 12, 'e': 13, 'f': 14, 'g': 15, 'h': 16, 'j': 17, 'k': 18, 'm': 19,
         'n': 20, 'p': 21, 'q': 22, 'r': 23, 's': 24, 't': 25, 'u': 26, 'v': 27, 'w': 28, 'x': 29,
         'y': 30, 'z': 31}
    lnglat = []
    for str in lnglat32:
        num = D[str]
        binary = num2Binary(num)
        lnglat += binary
    return lnglat

#lng, lat的geohash
def lngAndlat2lnglat32(lng, lat):
    #1-转化为二进制
    lngBinary = lng2LngBinary(lng)
    latBinary = lat2LatBinary(lat)
    #2-经纬度组合
    lnglat = lngLatCombine(lngBinary, latBinary)
    #3-转为32进制编码
    lnglat32 = lnglat2lnglat32(lnglat)
    return lnglat32

#lng, lat的geohash
def lnglat322lngAndlat(lnglat32):
    lnglat = lnglat322lnglat(lnglat32)
    lngBinary, latBinary = lngLatSplit(lnglat)
    lng = lngBinary2Lng(lngBinary)
    lat = latBinary2Lat(latBinary)
    return lng, lat

if __name__ == '__main__':
    #1-初始化经纬度
    lng, lat = 116.38955, 39.928167
    print("1-lng:{}, lat:{}".format(lng, lat))
    #2-转化为二进制
    lngBinary = lng2LngBinary(lng)
    latBinary = lat2LatBinary(lat)
    print("\n2-lngBinary:{}\nlatBinary:{}".format(lngBinary, latBinary))
    #2.1-二进制转回来
    lng = lngBinary2Lng(lngBinary)
    lat = latBinary2Lat(latBinary)
    print("\n2.1-lng:{}, lat:{}".format(lng, lat))
    #3-经纬度组合
    lnglat = lngLatCombine(lngBinary, latBinary)
    print("\n3-lnglat:{}".format(lnglat))
    #3.1-lnglat拆分为经纬度
    lngBinary, latBinary = lngLatSplit(lnglat)
    print("\n3.1-lngBinary:{}\nlatBinary:{}".format(lngBinary, latBinary))
    #4-转为32进制编码
    lnglat32 = lnglat2lnglat32(lnglat)
    print("\n4-lnglat32:{}".format(lnglat32))
    #4.1-32进制编码拆分为lnglat
    lnglat = lnglat322lnglat(lnglat32)
    print("\n4.1-lnglat:{}".format(lnglat))

    #5
    lng, lat = 116.38955, 39.928167
    print("\n5-lng:{}, lat:{}".format(lng, lat))
    #5.1-encode(整合1-4)
    lnglat32 = lngAndlat2lnglat32(lng, lat)
    print("\n5.1-lnglat32:{}".format(lnglat32))
    #5.2-decode
    lng, lat = lnglat322lngAndlat(lnglat32)
    print("\n5.2-lng:{}, lat:{}".format(lng, lat))

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值