Geohash

    举个例子来说明下Geohash的作用。

    我们需要搜索当前200米范围内的所有餐馆啊什么的。那么我们怎么去定位所有餐馆的位置呢?

    最普通的方法就是,算出当前位置能找到的餐馆的距离,然后在筛选出 ≤ 200 的餐馆。这样也是可以的,但是问题在于

一个城市有茫茫多的餐馆,每次定位都需要计算一次然后筛选。这个开销太大了。简直可以说是爆炸。然后就可以想想别的

方法了。按照正常的想法,我站在某个位置,那么最好的定位方法当然是以我为中心向外辐射200米。然后在这个区域内的

所有餐馆都是我想要的。这样的话,计算量就会小很多了。

    于是呢,出现了Geohash这个东东。下面是Geohash的原理。

    Geohash 原理:

    Geohash主要是把二维的地址坐标(经纬度)转换成一个一维的字符串标识。然后用这个标识来标注这个区域。具体的

编解码方法如下:

    经度的范围是 [-90, 90], 那么先划分成 [-90, 0), [0, 90]。 我们将这个划分为左右区域。当得到的经度在左区域的

时侯标注0, 在右区域的时候标注为1. 假定我们现在的坐标为 39.928167, 那么得到第一个标志位是1.

    然后在从[0, 90]进行二次划分,[0, 45), [45, 90]. 这时候 39.928167在左区域, 得到标志位是0,一次类推,我们

可以得到一窜1011100011(具体精确到多少个01 需要根据客户需求来定。)

    纬度的编码方式和经度的编码方式是一样的,只是范围是[-180, 180]。然后对116.389550进行编码,就会得到10

111 00011。

    然后根据偶数位放度,奇数位放度进行交替编码。

    我们得到的经度编码是: 11010 01011

    我们得到的纬度编码是: 10111 00011

    所以Geohash编码是: 11100 11101 00100 01111

        注: Geohash 编码的字符串是从0开始算起的,所以第一位是经度,然后纬度,然后经度。。。

    得到Geohash编码之后,五位五位的开始编码,所以是 28、29、4、15

   

    所以得到是Geohash 是 wx4g.

    下面是一些参考网站:

    https://en.wikipedia.org/wiki/Geohash

    http://www.cnblogs.com/LBSer/p/3310455.html

    http://www.cnblogs.com/dengxinglin/archive/2012/12/14/2817761.html

    下面是C++ 代码实现:

   

 1 string encodeGeohash(const double & theLat, const double & theLong, int thePrecision)
 2 {
 3     string aStrGeohash = "";
 4     double aLatStart = -90.000000;
 5     double aLatEnd = 90.000000;
 6     double aLongStart = -180.000000;
 7     double aLongEnd = 180.000000;
 8     double aLatMidPoint = (aLatStart + aLatEnd) / 2;
 9     double aLongMidPoint = (aLongStart + aLongEnd) / 2;
10     int aBit = 0;
11     int aCh = 0;
12     char aBits[] = {16, 8, 4, 2, 1};
13     const string BASEENCODE = "0123456789bcdefghjkmnpqrstuvwxyz";
14 
15     if(theLat < aLatStart || theLat > aLatEnd || theLong < aLongStart || theLong > aLongEnd)
16     {
17         return aStrGeohash;
18     }
19     //The Geohash first bit is longtitude
20     for(int i = 0; i < thePrecision; i++)
21     {
22         if(0 == i % 2)
23         {
24             if(theLong >= aLongMidPoint)
25             {
26                 aCh |= aBits[aBit];
27                 aLongStart = aLongMidPoint;
28             }
29             else
30             {
31                 aLongEnd = aLongMidPoint;
32             }
33             aLongMidPoint = (aLongStart + aLongEnd) / 2;
34         }
35         else
36         {
37             if(theLat >= aLatMidPoint)
38             {
39                 aCh |= aBits[aBit];
40                 aLatStart = aLatMidPoint;
41             }
42             else
43             {
44                 aLatEnd = aLatMidPoint;
45             }
46             aLatMidPoint = (aLatStart + aLatEnd) / 2;
47         }
48 
49         if(aBit < 4)
50         {
51             aBit++;
52         }
53         else
54         {
55             aStrGeohash += BASEENCODE[aCh];
56             aCh = 0;
57             aBit = 0;
58         }
59     }
60 
61     return aStrGeohash;
62 }

   

   

原文地址:https://www.cnblogs.com/AndyStudy/p/6398747.html