LBS地理位置距离计算方法之geohash算法

着移动终端的普及,很多应用都基于LBS功能,附近的某某(餐馆、银行、妹纸等等)。
基础数据中,一般保存了目标位置的经纬度;利用用户提供的经纬度,进行对比,从而获得是否在附近。这里需要在设置出一个字段,是关于编码的字段,一会看下文哈……


地理位置距离实现目标:
查找附近多少公里内的人或者商家

比如:微信、陌陌、美团、基于O2O的一些APP这些应用或者移动网页都需要用到地理位置计算

目前来说:移动地理位置距离计算比较好的算法是geohash,特此整理分享。

 

geohash有以下几个特点:

第一:geohash用一个字符串表示经度和纬度两个坐标。

某些情况下无法在两列上同时应用索引 (例如MySQL 4之前的版本,Google App Engine的数据层等),利用geohash,只需在一列上应用索引即可。

(这里插一句:我们的mysql为字段创建的索引,其实原理就是利用二分法算法来做路径查询简化,快速查找出想要的字段位置)

第二:geohash表示的并不是一个点,而是一个矩形区域。比如编码wx4g0ec19,它表示的是一个矩形区域。

使用者可以发布地址编码,既能表明自己位于北海公园附近,又不至于暴露自己的精确坐标,有助于隐私保护。

第三:编码的前缀可以表示更大的区域。


例如wx4g0ec1,它的前缀wx4g0e表示包含编码wx4g0ec1在内的更大范围。 这个特性可以用于附近地点搜索。首先根据用户当前坐标计算geohash(例如wx4g0ec1)然后取其前缀进行查询 (SELECT * FROM place WHERE geohash LIKE 'wx4g0e%'),即可查询附近的所有地点。

Geohash比直接用经纬度的高效很多。

 

Geohash的原理

Geohash的最简单的解释就是:将一个经纬度信息,转换成一个可以排序,可以比较的字符串编码

 

geohash能做到:

复制代码
require_once('geohash.class.php');
$geohash = new Geohash;
//得到这点的hash值
$hash = $geohash->encode(39.98123848, 116.30683690);
//取前缀,前缀约长范围越小
$prefix = substr($hash, 0, 6);
//取出相邻八个区域
$neighbors = $geohash->neighbors($prefix);
array_push($neighbors, $prefix);

print_r($neighbors);
复制代码
  • 得到9个geohash值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//得到9个geohash值
 
Array
(
   [top] => wx4eqx
   [bottom] => wx4eqt
   [right] => wx4eqy
   [left] => wx4eqq
   [topleft] => wx4eqr
   [topright] => wx4eqz
   [bottomright] => wx4eqv
   [bottomleft] => wx4eqm
   [0] => wx4eqw
)

  

  • 范围如图:
  • 用sql语句查询
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    SELECT  FROM  xy  WHERE  geohash  LIKE  'wx4eqw%' ;
    SELECT  FROM  xy  WHERE  geohash  LIKE  'wx4eqx%' ;
    SELECT  FROM  xy  WHERE  geohash  LIKE  'wx4eqt%' ;
    SELECT  FROM  xy  WHERE  geohash  LIKE  'wx4eqy%' ;
    SELECT  FROM  xy  WHERE  geohash  LIKE  'wx4eqq%' ;
    SELECT  FROM  xy  WHERE  geohash  LIKE  'wx4eqr%' ;
    SELECT  FROM  xy  WHERE  geohash  LIKE  'wx4eqz%' ;
    SELECT  FROM  xy  WHERE  geohash  LIKE  'wx4eqv%' ;
    SELECT  FROM  xy  WHERE  geohash  LIKE  'wx4eqm%' ;
  • 看一下是否用上索引 (一共有50多万行测试数据):
  • 索引:

<code class="lang-php"><img style="border: 0px currentColor; max-width: 900px;" alt="" src="http://images2015.cnblogs.com/blog/381809/201511/381809-20151124214003656-207022041.png" /><img style="border: 0px currentColor; max-width: 900px;" alt="" src="http://images2015.cnblogs.com/blog/381809/201511/381809-20151124214011812-983658835.png" />


</code><div class="save_code tracking-ad" data-mod="popu_249"><a target=_blank href="javascript:;" target="_blank"><img src="http://static.blog.csdn.net/images/save_snippets.png" alt="" /></a></div>

其他资料:

- geohash演示: http://openlocation.org/geohash/geohash-js/

- wiki: http://en.wikipedia.org/wiki/Geohash

- 原理: https://github.com/CloudSide/geohash/wiki

 

 

 

 

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值