参考文档:html
http://blog.csdn.net/wangxiafghj/article/details/9014363geohash 算法原理及实现方式
http://blog.charlee.li/geohash-intro/ geohash:用字符串实现附近地点搜索
http://blog.sina.com.cn/s/blog_7c05385f0101eofb.html 查找附近点--Geohash方案讨论
http://www.wubiao.info/372 查找附近的xxx 球面距离以及Geohash方案探讨
http://en.wikipedia.org/wiki/Haversine_formula Haversine formula球面距离公式
http://www.codecodex.com/wiki/Calculate_Distance_Between_Two_Points_on_a_Globe 球面距离公式代码实现
http://developer.baidu.com/map/jsdemo.htm#a6_1 球面距离公式验证
http://www.wubiao.info/470 Mysql or Mongodb LBS快速实现方案算法
如今不少APP都有搜索附近的功能,好比附近的人、附近的店铺等。要实现这样的功能,咱们能够用最笨的方法:根据经纬度计算距离,而后划定一个阈值,只要小于该阈值就算是附近的。这种方法在数据量小时基本没问题,可是,若是数据量特别大,那服务器就须要进行大量的计算,负担很重!为了解决这一类问题,一个比较经常使用的方法就是利用GeoHash。
1、简介
GeoHash是一种地址编码方法。他可以把二维的空间经纬度数据编码成一个字符串。GeoHash具备如下特色:
一、GeoHash用一个字符串表示经度和纬度两个坐标。在数据库中能够实如今一列上应用索引
二、GeoHash表示的并非一个点,而是一个区域;
三、GeoHash编码的前缀能够表示更大的区域。例如wx4g0ec1,它的前缀wx4g0e表示包含编码wx4g0ec1在内的更大范围。 这个特性能够用于附近地点搜索
2、计算方法:
GeoHash的计算过程分为三步:
一、将经纬度转换成二进制:
好比这样一个点(39.923201, 116.390705)
纬度的范围是(-90,90),其中间值为0。对于纬度39.923201,在区间(0,90)中,所以获得一个1;(0,90)区间的中间值为45度,纬度39.923201小于45,所以获得一个0,依次计算下去,便可获得纬度的二进制表示,以下表:
最后获得纬度的二进制表示为:
10111000110001111001
同理能够获得经度116.390705的二进制表示为:
11010010110001000100
二、合并纬度、经度的二进制:
合并方法是将经度、纬度二进制按照奇偶位合并:
11100 11101 00100 01111 00000 01101 01011 00001
三、按照Base32进行编码:
Base32编码表(其中一种):
将上述合并后二进制编码后结果为:
wx4g0ec1
3、GeoHash的精度
编码越长,表示的范围越小,位置也越精确。所以咱们就能够经过比较GeoHash匹配的位数来判断两个点之间的大概距离。
4、不足之处及解决方法
一、边缘附近的点,黄色的点要比黑色的点更加靠近红点,可是因为黑点跟红点的GeoHash前缀匹配数目更多,所以获得黑点更加靠近红点的结果
解决方法:
能够经过筛选周围8个区域内的全部点,而后计算距离获得知足条件结果。
二、由于现有的GeoHash算法使用的是Peano空间填充曲线(可感兴趣的可本身查看),这种曲线会产生突变,形成了编码虽然类似但距离可能相差很大的问题,所以在查询附近的时候,首先筛选GeoHash编码类似的点,而后进行实际距离计算。sql