首先感谢GeoHash核心原理解析这篇文章让我明白了什么叫geohash
在这篇文章里,作者提出了几个使用geohash的注意点:
由于GeoHash是将区域划分为一个个规则矩形,并对每个矩形进行编码,这样在查询附近POI信息时会导致以下问题,比如红色的点是我们的位 置,绿色的两个点分别是附近的两个餐馆,但是在查询的时候会发现距离较远餐馆的GeoHash编码与我们一样(因为在同一个GeoHash区域块上),而 较近餐馆的GeoHash编码与我们不一致。这个问题往往产生在边界处。
![]()
解决的思路很简单,我们查询时,除了使用定位点的GeoHash编码进行匹配外,还使用周围8个区域的GeoHash编码,这样可以避免这个问题。
那么如何得到周围8个区域的geohash编码呢,作者没有提供更明确的思路,在网上也搜索不到相关的解决办法,所以在这里提大家提供我的思路。
看到这里,我假设各位已经清楚如何对经纬度进行geohash编码。
在对经度进行二分逼近时,落在左边区间为0,右边为1:
第一次划分:
第二次划分:
第三次划分:
可以看出每一块区域的编码,从左往右依次对应了十进制的0~(2^n)-1,同样的,对纬度逼近的过程中,每一块区域从下往上同样依次对应0~(2^n)-1。
因此,很容易的就能求出周围区域的geohash值:
1. 将当前区域的geohash编码解码成经纬度对应的二进制串
2. 将二进制串+1或者-1就能得到左右经度(或上下纬度)区域对应的二进制串(注意边界)
3. 得到的经纬度二进制串两两组合再进行geohash的编码,得到的就是周围区域的编码了。
代码如下:
/**
* 求与当前geohash相邻的8个格子的geohash值。
* @param geohash
* @return string数组,周围格子的geohash值
* @throws LengthOutOfRangException
* geohash长度超出范围(<=12)
*/
public String[] expand(String geohash) throws LengthOutOfRangException {
if (geohash.length() > 12)
throw new LengthOutOfRangException("The length of geohash is out of range");
String bCoordinate = decodeToBinary(geohash);//当前geohash值对应的二进制串
StringBuilder bLat = new StringBuilder();
StringBuilder bLon = new StringBuilder();
for (int i = 0; i < bCoordinate.length(); i++) {
if ((i % 2) == 0) {
bLon.append(bCoordinate.charAt(i));
} else {
bLat.append(bCoordinate.charAt(i));
}
}
String lat = bLat.toString();
String lon = bLon.toString();
String downLat = calculate(lat, -1);
String upLat = calculate(lat, 1);
String leftLon = calculate(lon, -1);
String rightLon = calculate(lon, 1);
return new String[] { encode(upLat,leftLon), encode(upLat,lon), encode(upLat,rightLon), encode(lat,leftLon),
geohash, encode(lat,rightLon), encode(downLat,leftLon), encode(downLat,lon),
encode(downLat,rightLon) };
}
/**
* 计算当前格子左右(上下)格子的经(纬)度值二进制串
*
* @param coordinate
* 当前格子的经/纬度值
* @param i
* 偏移量
* @return
*/
private String calculate(String coordinate, int i) {
int length = coordinate.length();
String result = Integer.toBinaryString((Integer.valueOf(coordinate, 2) + i) + (1 << length)).substring(1);
if (result.length() != length) {
return null;
} else {
return result;
}
}
使用Geohash获取周围8个区域编码的方法
本文介绍了如何通过Geohash解决查询附近POI时出现的边界问题,提出在查询时同时考虑定位点及周围8个区域的GeoHash编码。详细解释了从经纬度二进制串加减1来获取相邻区域编码的思路,并提供了实现方法。
10万+

被折叠的 条评论
为什么被折叠?



