博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于计算周围多少里以内的楼盘
阅读量:6391 次
发布时间:2019-06-23

本文共 8669 字,大约阅读时间需要 28 分钟。

 

/**     * 根据经纬度计算距离 其中A($lat1,$lng1)、B($lat2,$lng2)         * 注意弧度角度的计算     * 单位:km     */    function _getDistance($lat1,$lng1,$lat2,$lng2)    {        //地球半径        $R = 6378.137; //km            //将角度转为狐度        $radLat1 = deg2rad($lat1);        $radLat2 = deg2rad($lat2);        $radLng1 = deg2rad($lng1);        $radLng2 = deg2rad($lng2);            //结果        $s = acos(cos($radLat1)*cos($radLat2)*cos($radLng1-$radLng2)+sin($radLat1)*sin($radLat2))*$R;            //精度        $s = round($s* 10000)/10000;        return  round($s);    }
 
/** *根据传入的中心点的经纬度和半径,计算出矩形区域 * @param float $center_lat * @param float $center_lng * @param int   $radius unit:km */function getAroundRectangle($center_lat, $center_lng, $radius){    //先来求东西两侧的的范围边界 经度    $earth_radius = 6378.137;    //km    $dlng = rad2deg(2 * asin(sin($radius / (2 * $earth_radius)) / cos(deg2rad($center_lat)))); //角度         //然后求南北两侧的范围边界 维度    $dlat = rad2deg($radius/$earth_radius);        $data = array(        'lat_min' => $center_lat-$dlat,//维度最小        'lat_max' => $center_lat+$dlat,//唯独 最大        'lng_min' => $center_lng-$dlng,//经度最小        'lng_max' => $center_lng+$dlng,//经度最大    );    return $data;}
 

 

 
View Code
1 /**  2  * Geohash generation class  3  * http://blog.dixo.net/downloads/  4  *  5  * This file copyright (C) 2008 Paul Dixon (paul@elphin.com)  6  *  7  * This program is free software; you can redistribute it and/or  8  * modify it under the terms of the GNU General Public License  9  * as published by the Free Software Foundation; either version 3 10  * of the License, or (at your option) any later version. 11  * 12  * This program is distributed in the hope that it will be useful, 13  * but WITHOUT ANY WARRANTY; without even the implied warranty of 14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 15  * GNU General Public License for more details. 16  * 17  * You should have received a copy of the GNU General Public License 18  * along with this program; if not, write to the Free Software 19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. 20  */ 21  22  23  24 /** 25 * Encode and decode geohashes 26 * 27 */ 28 class Geohash 29 { 30     private $coding="0123456789bcdefghjkmnpqrstuvwxyz"; 31     private $codingMap=array(); 32      33     public function Geohash() 34     { 35         //build map from encoding char to 0 padded bitfield 36         for($i=0; $i<32; $i++) 37         { 38             $this->codingMap[substr($this->coding,$i,1)]=str_pad(decbin($i), 5, "0", STR_PAD_LEFT); 39         } 40          41     } 42      43     /** 44     * Decode a geohash and return an array with decimal lat,long in it 45     */ 46     public function decode($hash) 47     { 48         //decode hash into binary string 49         $binary=""; 50         $hl=strlen($hash); 51         for($i=0; $i<$hl; $i++) 52         { 53             $binary.=$this->codingMap[substr($hash,$i,1)]; 54         } 55          56         //split the binary into lat and log binary strings 57         $bl=strlen($binary); 58         $blat=""; 59         $blong=""; 60         for ($i=0; $i<$bl; $i++) 61         { 62             if ($i%2) 63                 $blat=$blat.substr($binary,$i,1); 64             else 65                 $blong=$blong.substr($binary,$i,1); 66              67         } 68          69         //now concert to decimal 70         $lat=$this->binDecode($blat,-90,90); 71         $long=$this->binDecode($blong,-180,180); 72          73         //figure out how precise the bit count makes this calculation 74         $latErr=$this->calcError(strlen($blat),-90,90); 75         $longErr=$this->calcError(strlen($blong),-180,180); 76                  77         //how many decimal places should we use? There's a little art to 78         //this to ensure I get the same roundings as geohash.org 79         $latPlaces=max(1, -round(log10($latErr))) - 1; 80         $longPlaces=max(1, -round(log10($longErr))) - 1; 81          82         //round it 83         $lat=round($lat, $latPlaces); 84         $long=round($long, $longPlaces); 85          86         return array($lat,$long); 87     } 88  89      90     /** 91     * Encode a hash from given lat and long 92     */ 93     public function encode($lat,$long) 94     { 95         //how many bits does latitude need?     96         $plat=$this->precision($lat); 97         $latbits=1; 98         $err=45; 99         while($err>$plat)100         {101             $latbits++;102             $err/=2;103         }104         105         //how many bits does longitude need?106         $plong=$this->precision($long);107         $longbits=1;108         $err=90;109         while($err>$plong)110         {111             $longbits++;112             $err/=2;113         }114         115         //bit counts need to be equal116         $bits=max($latbits,$longbits);117         118         //as the hash create bits in groups of 5, lets not119         //waste any bits - lets bulk it up to a multiple of 5120         //and favour the longitude for any odd bits121         $longbits=$bits;122         $latbits=$bits;123         $addlong=1;124         while (($longbits+$latbits)%5 != 0)125         {126             $longbits+=$addlong;127             $latbits+=!$addlong;128             $addlong=!$addlong;129         }130         131         132         //encode each as binary string133         $blat=$this->binEncode($lat,-90,90, $latbits);134         $blong=$this->binEncode($long,-180,180,$longbits);135         136         //merge lat and long together137         $binary="";138         $uselong=1;139         while (strlen($blat)+strlen($blong))140         {141             if ($uselong)142             {143                 $binary=$binary.substr($blong,0,1);144                 $blong=substr($blong,1);145             }146             else147             {148                 $binary=$binary.substr($blat,0,1);149                 $blat=substr($blat,1);150             }151             $uselong=!$uselong;152         }153         154         //convert binary string to hash155         $hash="";156         for ($i=0; $i
coding[$n];160 }161 162 163 return $hash;164 }165 166 /**167 * What's the maximum error for $bits bits covering a range $min to $max168 */169 private function calcError($bits,$min,$max)170 {171 $err=($max-$min)/2;172 while ($bits--)173 $err/=2;174 return $err;175 }176 177 /*178 * returns precision of number179 * precision of 42 is 0.5180 * precision of 42.4 is 0.05181 * precision of 42.41 is 0.005 etc182 */183 private function precision($number)184 {185 $precision=0;186 $pt=strpos($number,'.');187 if ($pt!==false)188 {189 $precision=-(strlen($number)-$pt-1);190 }191 192 return pow(10,$precision)/2;193 }194 195 196 /**197 * create binary encoding of number as detailed in http://en.wikipedia.org/wiki/Geohash#Example198 * removing the tail recursion is left an exercise for the reader199 */200 private function binEncode($number, $min, $max, $bitcount)201 {202 if ($bitcount==0)203 return "";204 205 #echo "$bitcount: $min $max
";206 207 //this is our mid point - we will produce a bit to say208 //whether $number is above or below this mid point209 $mid=($min+$max)/2;210 if ($number>$mid)211 return "1".$this->binEncode($number, $mid, $max,$bitcount-1);212 else213 return "0".$this->binEncode($number, $min, $mid,$bitcount-1);214 }215 216 217 /**218 * decodes binary encoding of number as detailed in http://en.wikipedia.org/wiki/Geohash#Example219 * removing the tail recursion is left an exercise for the reader220 */221 private function binDecode($binary, $min, $max)222 {223 $mid=($min+$max)/2;224 225 if (strlen($binary)==0)226 return $mid;227 228 $bit=substr($binary,0,1);229 $binary=substr($binary,1);230 231 if ($bit==1)232 return $this->binDecode($binary, $mid, $max);233 else234 return $this->binDecode($binary, $min, $mid);235 }236 }

 

方案1:

  根据中心点,和 上面的算法计算出几公里以内的最大/最小经纬度,然后搜索时用这个条件 (我们想要的为圆型的,需要过滤一次数据在),使用于数据量相对较小的

缺点:1.范围比较的索引利用率并不高,2.SQL语句极其不稳定(不同的当前位置会产生完全不同的SQL查询),很难缓存。

方案2:

  运用geohash, geohash是一种地址编码,它能把二维的经纬度编码成一维的字符串, 字符串匹配度越大,离的越近,适用于数据量较大的,

缺点:匹配程度并不能准确控制距离,只能找出比他大的范围,然后在用程序去判断

文章链接:

 

  

 

转载地址:http://nbsha.baihongyu.com/

你可能感兴趣的文章
matlab-线性代数 非齐次方程组 判断是否有唯一解
查看>>
RBAC权限管理总结
查看>>
Hadoop之父Doug Cutting
查看>>
Linux 实时流量监测(iptraf中文图解)
查看>>
大家好
查看>>
Linux软件包管理
查看>>
IT运维之感悟
查看>>
根据 JS 自动定义页面缩放比(根据分辨率进行适配)
查看>>
Mysql 数据库命令行导出导入sql脚本
查看>>
SqlServer中循环给多张表建立聚簇索引
查看>>
给定二叉树先序、中序遍历序列,求后序遍历
查看>>
OX Pattern
查看>>
我的友情链接
查看>>
安全日志分析工具
查看>>
CloudStack 制作window模板
查看>>
flash程序员2012最大转变
查看>>
路由表基础知识
查看>>
IT规划中的技术体系架构
查看>>
OSPF:Forwarding Address in NSSA External LSA
查看>>
一个虚拟机网络的XML描述
查看>>