2.1 区间[-90,90]进行二分为[-90,0),[0,90],称为左右区间,可以确定39.928167属于右区间[0,90],给标记为1;
2.2 接着将区间[0,90]进行二分为 [0,45),[45,90],可以确定39.928167属于左区间 [0,45),给标记为0;
2.3 递归上述过程39.928167总是属于某个区间[a,b]。随着每次迭代区间[a,b]总在缩小,并越来越逼近39.928167;
2.4 这样随着算法的进行会产生一个序列1011100011的纬度二进制编码;
- 同理,计算出地球经度二进制,区间是[-180,180],可以对经度116.389550进行编码。算出结果1101001011;
- 组码:通过上述计算,纬度产生的编码为10111 00011,经度产生的编码为11010 01011。偶数位放经度,奇数位放纬度,把2串编码组合生成新串:11100 11101 00100 01111。
- 使用用0-9、b-z(去掉a, i, l, o)这32个字母进行base32编码,首先将11100 11101 00100 01111转成十进制,对应着28、29、4、15,十进制对应的编码就是wx4g。
Geohash其实就是将整个地图或者某个分割所得的区域进行一次划分,由于采用的是base32编码方式,即Geohash中的每一个字母或者数字(如wx4g0e中的w)都是由5bits组成(2^5 = 32,base32),这5bits可以有32中不同的组合(0~31),这样我们可以将整个地图区域分为32个区域,通过00000 ~ 11111来标识这32个区域。第一次对地图划分后的情况如下图所示(每个区域中的编号对应于该区域所对应的编码):
进行多次分解后,我们就可以得到更精确的位置划分,如上述计算的wx4g已经可以精确到一个城市城区了:
从上图中可以看出,相邻城区的geoHash值的共同前缀越多,由此我们就可以应用共同前缀来判断附近相邻的位置了。当然精确范围也是根据经纬度和hash值的范围来确定的,如下表,geo精确到8位的共同前缀,可以表示附近约20米内的范围了:
在PHP中的实现与应用
在了解了geo的位置算法原理后,PHP开发过程中我们便可以使用这一定位功能,目前解决位置定位和搜索功能的方案有很多种,基于PHP的,从本人自身实践中推荐一下几种: