Geohash——地理坐标索引

今天看july的博客:第三十六~三十七章、搜索智能提示suggestion,附近地点搜索

http://blog.csdn.net/v_july_v/article/details/11288807

里面提到了geohash算法对地理坐标的索引,但是引用的文章和例子让我产生了疑问,对于坐标的经纬度不应该是直接让纬度跟随在经度之后形成一个索引值的,这样只能保证经度相同的且靠近的点排列的比较近,而纬度相同经度只差1的点确不能排列的比较近。

于是查阅了geohash的维基百科说明:http://en.wikipedia.org/wiki/Geohash#Decode_from_base_32

文中举了个例子:

This operation results in the bits 01101 11111 11000 00100 00010. Assuming that counting starts at 0 in the left side, the even bits are taken for the longitude code (0111110000000), while the odd bits are taken for the latitude code (101111001001).

原来是经度和纬度相互交错形成的geohash值。这样就能比较好的让靠近的点按照geohash值也能排列的靠近一些。

写了一段程序来看看经纬度(x坐标和y坐标)互相交错形成的有序值对应的坐标是多少。

//vs2008

#include "stdafx.h"
#include <atlstr.h>
#include <conio.h>

void GetEvenAndOdd(int nNum, int &nEven, int &nOdd)
{
    int k = 1;
    nEven = nOdd = 0;
    for (int i = 0; i < 8; i++)
    {
        if (0 != i%2)
        {
            nEven += k*(nNum & 1);
        } 
        else
        {
            nOdd += k*(nNum & 1);
        }
        if (0 != i%2) k *= 2;
        nNum = nNum >> 1;
    }
}

CString GetBinaryString(int nNum, int nLen)
{
    CString csRet;
    for (int i = nLen; i > 0; i--)
    {
        if ((nNum >> (i-1)) & 1)
            csRet += "1";
        else
            csRet += "0";
    }
    return csRet;
}

int _tmain(int argc, _TCHAR* argv[])
{
    printf("十进制	geohash值	偶    奇    坐标值\n");
    for (int i = 0; i < 64; i++)
    {
        int nEven, nOdd;
        GetEvenAndOdd(i, nEven, nOdd);
         CString strGeohash = GetBinaryString(i, 8);
         CString strEven    = GetBinaryString(nEven, 4);
         CString strOdd     = GetBinaryString(nOdd, 4);
        printf("%02d\t%S\t%S\t%S\t(%d,%d)\n", i, strGeohash.GetBuffer(), 
            strEven.GetBuffer(), strOdd.GetBuffer(), nEven, nOdd);
    }
    _getch();
	return 0;
}

跑出来的坐标值如下:

十进制 geohash值 坐标值 十进制 geohash 值 坐标值
00 00000000 0000 0000 (0,0) 32 00100000 0100 0000 (4,0)
01 00000001 0000 0001 (0,1) 33 00100001 0100 0001 (4,1)
02 00000010 0001 0000 (1,0) 34 00100010 0101 0000 (5,0)
03 00000011 0001 0001 (1,1) 35 00100011 0101 0001 (5,1)
04 00000100 0000 0010 (0,2) 36 00100100 0100 0010 (4,2)
05 00000101 0000 0011 (0,3) 37 00100101 0100 0011 (4,3)
06 00000110 0001 0010 (1,2) 38 00100110 0101 0010 (5,2)
07 00000111 0001 0011 (1,3) 39 00100111 0101 0011 (5,3)
08 00001000 0010 0000 (2,0) 40 00101000 0110 0000 (6,0)
09 00001001 0010 0001 (2,1) 41 00101001 0110 0001 (6,1)
10 00001010 0011 0000 (3,0) 42 00101010 0111 0000 (7,0)
11 00001011 0011 0001 (3,1) 43 00101011 0111 0001 (7,1)
12 00001100 0010 0010 (2,2) 44 00101100 0110 0010 (6,2)
13 00001101 0010 0011 (2,3) 45 00101101 0110 0011 (6,3)
14 00001110 0011 0010 (3,2) 46 00101110 0111 0010 (7,2)
15 00001111 0011 0011 (3,3) 47 00101111 0111 0011 (7,3)
16 00010000 0000 0100 (0,4) 48 00110000 0100 0100 (4,4)
17 00010001 0000 0101 (0,5) 49 00110001 0100 0101 (4,5)
18 00010010 0001 0100 (1,4) 50 00110010 0101 0100 (5,4)
19 00010011 0001 0101 (1,5) 51 00110011 0101 0101 (5,5)
20 00010100 0000 0110 (0,6) 52 00110100 0100 0110 (4,6)
21 00010101 0000 0111 (0,7) 53 00110101 0100 0111 (4,7)
22 00010110 0001 0110 (1,6) 54 00110110 0101 0110 (5,6)
23 00010111 0001 0111 (1,7) 55 00110111 0101 0111 (5,7)
24 00011000 0010 0100 (2,4) 56 00111000 0110 0100 (6,4)
25 00011001 0010 0101 (2,5) 57 00111001 0110 0101 (6,5)
26 00011010 0011 0100 (3,4) 58 00111010 0111 0100 (7,4)
27 00011011 0011 0101 (3,5) 59 00111011 0111 0101 (7,5)
28 00011100 0010 0110 (2,6) 60 00111100 0110 0110 (6,6)
29 00011101 0010 0111 (2,7) 61 00111101 0110 0111 (6,7)
30 00011110 0011 0110 (3,6) 62 00111110 0111 0110 (7,6)
31 00011111 0011 0111 (3,7) 63 00111111 0111 0111 (7,7)

将坐标点依次在坐标系上连起来如下图:


可以看出来,geohash和 july文中讲述的R数方法有图形上的分区域相似之处,这种编码方式在区块内尽可能的让邻近点的索引值靠近,但在区块与区块之间还是存在跳跃的地方。所以只简单使用这一种编码技术并不能完全解决邻近点搜索的问题。

要想完美解决问题,还需要考虑的更多一些。

这些问题留待以后继续研究。先写这么多吧。

update:

早上起来搜索了下别人的文章,看到了下面的话:

geohash的最大用途就是附近地址搜索了。不过,从geohash的编码算法中可以看出它的一个缺点:位于格子边界两侧的两点, 虽然十分接近,但编码会完全不同。实际应用中,可以同时搜索当前格子周围的8个格子,即可解决这个问题。

(from: http://tech.idv2.com/2011/07/05/geohash-intro/)




猜你喜欢

转载自blog.csdn.net/sun2043430/article/details/11854547