zoukankan      html  css  js  c++  java
  • 关于计算周围多少里以内的楼盘

        /**
         * 根据经纬度计算距离 其中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 equal
    116         $bits=max($latbits,$longbits);
    117         
    118         //as the hash create bits in groups of 5, lets not
    119         //waste any bits - lets bulk it up to a multiple of 5
    120         //and favour the longitude for any odd bits
    121         $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 string
    133         $blat=$this->binEncode($lat,-90,90, $latbits);
    134         $blong=$this->binEncode($long,-180,180,$longbits);
    135         
    136         //merge lat and long together
    137         $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             else
    147             {
    148                 $binary=$binary.substr($blat,0,1);
    149                 $blat=substr($blat,1);
    150             }
    151             $uselong=!$uselong;
    152         }
    153         
    154         //convert binary string to hash
    155         $hash="";
    156         for ($i=0; $i<strlen($binary); $i+=5)
    157         {
    158             $n=bindec(substr($binary,$i,5));
    159             $hash=$hash.$this->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 $max
    168     */
    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 number
    179     * precision of 42 is 0.5
    180     * precision of 42.4 is 0.05
    181     * precision of 42.41 is 0.005 etc
    182     */
    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#Example
    198     * removing the tail recursion is left an exercise for the reader
    199     */
    200     private function binEncode($number, $min, $max, $bitcount)
    201     {
    202         if ($bitcount==0)
    203             return "";
    204         
    205         #echo "$bitcount: $min $max<br>";
    206             
    207         //this is our mid point - we will produce a bit to say
    208         //whether $number is above or below this mid point
    209         $mid=($min+$max)/2;
    210         if ($number>$mid)
    211             return "1".$this->binEncode($number, $mid, $max,$bitcount-1);
    212         else
    213             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#Example
    219     * removing the tail recursion is left an exercise for the reader
    220     */
    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         else
    234             return $this->binDecode($binary, $min, $mid);
    235     }
    236 }

    方案1:

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

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

    方案2:

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

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

    文章链接:

    http://tech.idv2.com/2011/06/17/location-search/

    http://tech.idv2.com/2011/07/05/geohash-intro/

    http://www.wubiao.info/401

      

  • 相关阅读:
    order by子句
    having和where的区别
    O2O模式为什么这么火
    高德----------百度地图
    list后台转化为JSON的方法ajax
    ajax中后台string转json
    ERROR: JDWP Unable to get JNI 1.2 environment, jvm->GetEnv() return code = -2
    压缩文件解压
    个人作业3——个人总结(Alpha阶段)
    第08周-集合与泛型
  • 原文地址:https://www.cnblogs.com/siqi/p/3037888.html
Copyright © 2011-2022 走看看