PHP进阶学习之Geo的地图定位算法详解
php  /  管理员 发布于 7年前   167
本文实例讲述了PHP进阶学习之Geo的地图定位算法。分享给大家供大家参考,具体如下: 前言 日常开发中我们经常需要查找某个物体的定位,或者查找附近的范围等,我们自然而然会想到的方法就是利用各种提供服务的地图网站的API,基于API,用经纬度去实现定位和查找附近范围等等。然而,由于原理没有做一个了解和一定的认识,在对比距离远近关系或者控制精确程度方面,我们并不了解怎么利用这些经纬度数值去实现距离转化和对比。本章节我们就来探讨一下基于geo的位置算法原理。 在实际应用中,如果要用两个维度去确定一个点,则计算量会很大,因为一个二维确定一个平面,如果我们把二维平面上的所有点都用一个数字表示,即经纬度换算成一个字符串,则可以转为一维坐标来表示,大大减少计算量。这就是现在应用广泛的geoHash。 geoHash:Geohash是公共领域地理编码系统,它将地理位置编码为一串字母和数字。Geohash提供了像任意精度这样的属性,以及逐渐从代码末尾删除字符以减小其大小(并逐渐失去精度)的可能性。由于逐步精度下降的结果,附近的地方往往(但不总是)呈现类似的前缀。共享前缀越长,两个地方越接近。 能将一个地球上的点表示成一串字母,并且相近的地点字母的共同前缀越多。这能让位置搜索在开发中变得很容易。它的原理就是依据上述说的geoHash值。下面就来详细说明geoHash值是怎么算出来的: Geohash其实就是将整个地图或者某个分割所得的区域进行一次划分,由于采用的是base32编码方式,即Geohash中的每一个字母或者数字(如wx4g0e中的w)都是由5bits组成(2^5 = 32,base32),这5bits可以有32中不同的组合(0~31),这样我们可以将整个地图区域分为32个区域,通过00000 ~ 11111来标识这32个区域。第一次对地图划分后的情况如下图所示(每个区域中的编号对应于该区域所对应的编码): 在了解了geo的位置算法原理后,PHP开发过程中我们便可以使用这一定位功能,目前解决位置定位和搜索功能的方案有很多种,基于PHP的,从本人自身实践中推荐一下几种: GeoHash算法是一种将二维坐标换算成一位字符串的算法,可以通过不同字符串的共同前缀来判断相距远近。在日常业务中也常常需要用到,本文也介绍了不同的实现方法,具体实现方案还需以实际业务需要为准。如果属于精确度要求很高或者企业级的大规模应用,可以首先考虑MongoDB或者其他提供Geo功能的存储组件,如果较为轻量级,可以借助第三方地区API、或者利用redis做geo的简单应用。如果业务需求复杂度不高,在这里并不推荐直接使用PHP写,毕竟效率会比较低,而且这也不是业务关注的重点,所以没必要重新造轮子。 更多关于PHP相关内容感兴趣的读者可查看本站专题:《php面向对象程序设计入门教程》、《PHP数组(Array)操作技巧大全》、《PHP基本语法入门教程》、《PHP运算与运算符用法总结》、《php字符串(string)用法总结》、《php+mysql数据库操作入门教程》及《php常见数据库操作技巧汇总》 希望本文所述对大家PHP程序设计有所帮助。概念
原理
2.1 区间[-90,90]进行二分为[-90,0),[0,90],称为左右区间,可以确定39.928167属于右区间[0,90],给标记为1;
2.2 接着将区间[0,90]进行二分为 [0,45),[45,90],可以确定39.928167属于左区间 [0,45),给标记为0;
2.3 递归上述过程39.928167总是属于某个区间[a,b]。随着每次迭代区间[a,b]总在缩小,并越来越逼近39.928167;
2.4 这样随着算法的进行会产生一个序列1011100011的纬度二进制编码;
进行多次分解后,我们就可以得到更精确的位置划分,如上述计算的wx4g已经可以精确到一个城市城区了:
从上图中可以看出,相邻城区的geoHash值的共同前缀越多,由此我们就可以应用共同前缀来判断附近相邻的位置了。当然精确范围也是根据经纬度和hash值的范围来确定的,如下表,geo精确到8位的共同前缀,可以表示附近约20米内的范围了:在PHP中的实现与应用
实际应用中我们常常以商品、人物作为value值,以geohash值作为score,这样就可以搜索一定范围内score内的人或事物了。如搜索一定半径内的value:
$redis->geoRadius($key, $longitude, $latitude, $radius, $unit [, Array $options]);
或者如果只需要计算GeoHash值,可以使用网上广泛转发的一个计算Hash值的PHP方法:private $coding = '0123456789bcdefghjkmnpqrstuvwxyz';/*** calculate geoHash by longitude and latitude* @param $lat* @param $long* @return string*/public function calcGeoHash($lat,$long){$plat=$this->precision($lat);$latbits=1;$err=45;while($err>$plat){$latbits++;$err/=2;}$plong=$this->precision($long);$longbits=1;$err=90;while($err>$plong){$longbits++;$err/=2;}$bits=max($latbits,$longbits);$longbits=$bits;$latbits=$bits;$addlong=1;while (($longbits+$latbits)%5 != 0){$longbits+=$addlong;$latbits+=!$addlong;$addlong=!$addlong;}$blat=$this->binEncode($lat,-90,90, $latbits);$blong=$this->binEncode($long,-180,180,$longbits);$binary='';$uselong=1;while (strlen($blat)+strlen($blong)){if ($uselong){$binary=$binary.substr($blong,0,1);$blong=substr($blong,1);}else{$binary=$binary.substr($blat,0,1);$blat=substr($blat,1);}$uselong=!$uselong;}$hash='';for ($i=0; $i
总结
您可能感兴趣的文章:
122 在
学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..123 在
Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..原梓番博客 在
在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..博主 在
佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..1111 在
佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
Copyright·© 2019 侯体宗版权所有·
粤ICP备20027696号