介绍
GeoHash是一种空间地址编码方法,能够把二维的空间经纬度数据编码成一个字符串。
一个字符串代表某一矩形区域,矩形区域内所有的点都共享相同的GeoHash字符串。相当于给区域内的点做了一个索引。
算法过程
对一个地理坐标编码时,按照初始区间范围纬度[-90,90]和经度[-180,180],计算目标经度和纬度分别落在左区间还是右区间。落在左区间则取0,右区间则取1。然后,对上一步得到的区间继续按照此方法对半查找,得到下一位二进制编码。当编码长度达到业务的进度需求后,根据“偶数位放经度,奇数位放纬度”的规则,将得到的二进制编码穿插组合,得到一个新的二进制串。最后,根据base32的对照表,将二进制串翻译成字符串,即得到地理坐标对应的目标GeoHash字符串。
注意:北纬为正、南纬为负,东经为正、西经为负。
为什么经纬度交错
保证相近的点,有相同的前缀。
base32算法
包含数字、小写字母。去掉a、i、l、o这4个字母。
字符串中的每一位和位置的关系
奇数位、纬度
偶数位、经度
特征
算法实际上就是对一个区域不断分形,分形的次数越多,表示的区域越小,精度越高。
公共前缀的长度越长,这两个点距离越近。反之,不成立。
精度计算
一般来说8位可以满足一般需求。
计算两个点之间的举例
double geohashGetDistance(double lon1d, double lat1d, double lon2d, double lat2d) {
double lat1r, lon1r, lat2r, lon2r, u, v;
lat1r = deg_rad(lat1d);
lon1r = deg_rad(lon1d);
lat2r = deg_rad(lat2d);
lon2r = deg_rad(lon2d);
u = sin((lat2r - lat1r) / 2);
v = sin((lon2r - lon1r) / 2);
return 2.0 * EARTH_RADIUS_IN_METERS *
asin(sqrt(u * u + cos(lat1r) * cos(lat2r) * v * v));
}
当区域较小(10km*10km)时,可以使用泰勒展式简化计算,避免计算三角函数。
获取点附近的八个区域
可以根据位置关系,推算出点附近的八个区域。效率很高。
组件支持
Redis
PostgreSQL
网址
http://api.map.baidu.com/lbsapi/getpoint/index.html 获取经纬度
http://geohash.co/ 经纬度和geohash转换
https://en.wikipedia.org/wiki/Geohash
标签:rad,double,索引,算法,GeoHash,lat1r,字符串,deg From: https://www.cnblogs.com/txtp/p/16657238.html