根据GEOHASH,查找附近的人,判断距离远

思路:提取用户经纬度,生成GEOHASH,根据geohash的精度判断距离远近,结合
http://bbs.appcan.cn/forum.php?m … 7391&extra=page%3D1
这个帖子,可以完全计算出附近的人以及精确的距离(不过微信用的是大致距离,计算精确距离太耗费资源了。)

先普及一下GEOHASH的知识:

http://blog.jobbole.com/80633/
 GEO核心原理,懒得复制了,大家移步看一下就好了。

反正就是可以把精度和维度,这两段数字,处理成一段若干长度的字符,这一串字符越长,距离信息越精确,同时,两个人的距离越近,GEOHASH的字符越接近。

比如我在B点,我的经纬度转换成GEOHASH是:45sadfdagfgfa43

你在A店,你的经纬度转换成GEOHASH是:       45sadfdagfgfg34

我可以根据geohash的字符位数情况,判断两点的大致距离。

判断依据:

《根据GEOHASH,查找附近的人,判断距离远》

从上图可以看出,当GEOHASH长度为8的时候,转换成经纬度的长度是20位,那么距离误差是正负0.019千米。

长度为7,那么距离误差是正负0.076千米。

好了。有了这个思路,就OK了。

我们把每个人的经纬度都转换成geohash,根据geohash选择周围的事物距离,比如截取geohash前5位,进行对比,前五位全部相同,说明这些geohash距离是2.4公里以内的(微信的附近人最远就是2.5公里,估计也是这个东西搞出来的)

那么,怎么取得GEOHASH呢?

别的不会,对PHP稍有了解。网上翻了翻,就用PHP的GEOHASH扩展来搞。

首先下载gethub,把他**到自己的服务器里,


https://github.com/shenzhe/geohash

从新编译PHP:

然后到geohash目录。

执行:phpize  (最好带上PHP安装目录的绝对路径)

./configure

make

make install

然后把 geohash.so 加入到php.ini中

装好之后看一下PHPINFO是否成功启用了。

然后就可以直接在PHP页面里转换了:

/** *  $latitude    //纬度

*  $longitude   //经度

*  $precision   //精密度, 默认是12

*  返回 $precision 长度的 string 

*/

geohash_encode($latitude, $longitude, $precision=12);  

/**

*  $hash    //geohash_encode后的值

*  返回 array // Array

*                  (

*                      [latitude] => 39.416916975752

*                      [longitude] => 100.92223992571

*                      [north] => 39.416917059571

*                      [east] => 100.92224009335

*                      [south] => 100.92223992571

*                      [west] => 100.92223975807

*                  )

*/

geohash_decode($hash);

/**

*  $hash    //geohash_encode后的值

*  返回 在$hash 8个 (东南西北各二个)附近的hash值

*/

geohash_neighbors($hash);

/**

*  $precision    //精密度

*  返回 数组,array(“width”=>12.0, “height”=>12.0) 

*  表示矩形的宽和高

*/

geohash_dimension($hash);

上面教程是gethub里复制的,有问题可以私信我。

通过geohash_encode取得hash之后,我们可以通过各种方式,将他截取下来,

然后作为KEY,写入redis或者mysql。(强烈建议用redis,用起来太爽了)

我直接写了一个方法,根据各种距离,返回不同的字符长度

        function getgeohash($lat,$log){

                $geohash=geohash_encode($lat,$log,12); //取得原始GEOHASH

                $arr[‘0’]=$geohash;//原始HASH

                $arr[‘9’]=substr($geohash,0,9); //9位hash 距离最精确,

                $arr[‘8’]=substr($geohash,0,8);//8位,距离相对精确,具体精度看上面的表。

                $arr[‘7’]=substr($geohash,0,7);//7位,距离也挺精确

                $arr[‘6’]=substr($geohash,0,6);

                $arr[‘5’]=substr($geohash,0,5);

                $arr[‘4’]=substr($geohash,0,4);//4位hash,只要前4位相同,可以找出附近20KM的人事物。

                return $arr;

        }

redis的PHP扩展不解释了,有疑问的可以私信我。

$redis->sAdd(‘near:near:’.$arr[4],value);//20KM内的事物集合。

$redis->sAdd(‘near:near:’.$arr[5],value);//2.4KM内的事物集合。

$redis->sAdd(‘near:near:’.$arr[6],value);//0.61KM内的事物集合。

$redis->sAdd(‘near:near:’.$arr[7],value);//0.076KM内的事物集合。

$redis->sAdd(‘near:near:’.$arr[8],value);//0.019KM内的事物集合。

这里的$value,各位随意存数据,可以是用户信息的json,或者只放一个用户的uid随意啦。

‘near:near
《根据GEOHASH,查找附近的人,判断距离远》
arr[4-8] 这主要作寻址用,各位可以自己配置自己的路径,是各个数据集的key,根据情况酌情取就行了。

使用:

用户A,登陆后,先写入redis:

$redis->sAdd(‘near:near:’.$arr[4],value);//20KM内的事物集合。

当用户选择查询周围20KM的事物,

直接取得用户当前的geohash,然后截取geohash前4位。如:$geoarr[4];

然后读取redis

$redis->sort(‘near:near:’.$geoarr[4]);

这里直接返回了所有20KM内用户的集合。

不明白的私信吧,如果redis搞不定,可以用mysql存。

用redis有一个好处是可以结合sting或者hash等设置过期时间,比如30分钟后自动生效,这个各位自己摸索吧。

我这边的产品未成形,没有完整代码共享。看
杨焕昭
朋友发的:计算两个经纬度之间的直线距离
http://bbs.appcan.cn/forum.php?m … 1&fromuid=55258

一时脑热,我也发一个,,,很轻松就实现了附近人,或者摇一摇搜索附近人,附近商家,等等好玩的东西。

##############################################################

下面评论的哥们给了一个geohash的github地址

“`

    – https://github.com/CloudSide/geohash

“`

https://blog.csdn.net/qq_36373262/article/details/62419390

    原文作者:varyall
    原文地址: https://blog.csdn.net/varyall/article/details/80973343
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞