Search for the geohash algorithm and implementation of nearby sites (PHP version)

Source: Internet
Author: User
For more information about the geohash algorithm and implementation of nearby sites (PHP version), see:

Principle and implementation of http://blog.csdn.net/wangxiafghj/article/details/9014363geohash algorithm
Http://blog.charlee.li/geohash-intro/ geohash: nearby location search with strings
A discussion on Geohash scheme for finding nearby points in http://blog.sina.com.cn/s/blog_7c05385f0101eofb.html
Study on xxx spherical distance and Geohash scheme in http://www.wubiao.info/372 searching
Formula for http://en.wikipedia.org/wiki/Haversine_formula Haversine formula spherical distance
Code implementation of http://www.codecodex.com/wiki/Calculate_Distance_Between_Two_Points_on_a_Globe spherical distance formula
Http://developer.baidu.com/map/jsdemo.htm#a6_1 spherical distance formula verification
Fast implementation of http://www.wubiao.info/470 Mysql or Mongodb LBS


Geohash has the following features:

First, geohash uses a string to represent the longitude and latitude coordinates. In some cases, indexes cannot be applied on both columns at the same time (for example, MySQL 4 and Google App Engine data layer). With geohash, you only need to apply indexes on one column.

Second, geohash represents not a vertex, but a rectangular area. For example, wx4425ec19 indicates a rectangular area. Users can publish address codes, indicating that they are located near Beihai Park, without exposing their precise coordinates, which helps privacy protection.

Third, the encoding prefix can indicate a larger region. For example, wx4g0ec1, whose prefix wx4g0e indicates a larger range including the encoded wx4g0ec1. This feature can be used to search nearby locations. First, geohash (for example, wx4g0ec1) is calculated based on the current coordinate of the user, and then the prefix is obtained for query (SELECT * FROM place WHERE geohash LIKE 'wx4g0e % ') to query all nearby locations.

Geohash is much more efficient than using longitude and latitude directly.


Geohash algorithm implementation (PHP version)

 codingMap[substr($this->coding,$i,1)]=str_pad(decbin($i), 5, "0", STR_PAD_LEFT);        }      }      public function decode($hash)    {        $binary="";        $hl=strlen($hash);        for($i=0; $i<$hl; $i++)        {            $binary.=$this->codingMap[substr($hash,$i,1)];        }          $bl=strlen($binary);        $blat="";        $blong="";        for ($i=0; $i<$bl; $i++)        {            if ($i%2)                $blat=$blat.substr($binary,$i,1);            else                $blong=$blong.substr($binary,$i,1);          }           $lat=$this->binDecode($blat,-90,90);         $long=$this->binDecode($blong,-180,180);        // $lat=$this->binDecode($blat,2,54);        // $long=$this->binDecode($blong,72,136);          $latErr=$this->calcError(strlen($blat),-90,90);        $longErr=$this->calcError(strlen($blong),-180,180);          $latPlaces=max(1, -round(log10($latErr))) - 1;        $longPlaces=max(1, -round(log10($longErr))) - 1;          $lat=round($lat, $latPlaces);        $long=round($long, $longPlaces);          return array($lat,$long);    }      public function encode($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
 
  coding[$n];        }          return $hash;    }      private function calcError($bits,$min,$max)    {        $err=($max-$min)/2;        while ($bits--)            $err/=2;        return $err;    }      private function precision($number)    {        $precision=0;        $pt=strpos($number,'.');        if ($pt!==false)        {            $precision=-(strlen($number)-$pt-1);        }          return pow(10,$precision)/2;    }      private function binEncode($number, $min, $max, $bitcount)    {        if ($bitcount==0)            return "";        $mid=($min+$max)/2;        if ($number>$mid)            return "1".$this->binEncode($number, $mid, $max,$bitcount-1);        else            return "0".$this->binEncode($number, $min, $mid,$bitcount-1);    }      private function binDecode($binary, $min, $max)    {        $mid=($min+$max)/2;          if (strlen($binary)==0)            return $mid;          $bit=substr($binary,0,1);        $binary=substr($binary,1);          if ($bit==1)            return $this->binDecode($binary, $mid, $max);        else            return $this->binDecode($binary, $min, $mid);    }}  ?>
 

Test instance

 
The following outlets are closest to me: "; // start $ B _time = microtime (true); // solution A: directly use the database storage function to traverse the sorting. // solution B geohash is used to find the nearest node, then sort // The current geohash value $ n_geohash = $ geohash-> encode ($ n_latitude, $ n_longpolling); // nearby $ n = 3; $ like_geohash = substr ($ n_geohash, 0, $ n); $ SQL = 'select * from retailersinfotable where geohash like "'. $ like_geohash. '% "'; $ query = mysql_query ($ SQL); if (mysql_num_rows ($ query) {while ($ row = mysql_fetch_array ($ query )) {$ data [] = array ("latitude" => $ row ["Latitude"], "longpolling" => $ row ["longpolling"], "name" => $ row ["RetailersName"],) ;}// calculate the actual distance from foreach ($ data as $ key => $ val) {$ distance = getDistance ($ n_latitude, $ n_longpolling, $ val ['latitude '], $ val ['longyun']); $ data [$ key] ['distance '] = $ distance; // sorting column $ sortdistance [$ key] = $ distance;} // array_multisort ($ sortdistance, SORT_ASC, $ data); // end $ e_time = microtime (true); echo "(computing time:"; echo $ e_time-$ B _time; echo "seconds)
"; // Var_dump ($ data); foreach ($ data as $ key => $ val) {echo"
"; Echo $ val ['distance ']. "Meters -------". $ val ['name'];} /*** @ desc calculate the distance * @ param float $ latitude value * @ param float $ longpolling longitude value */function getDistance ($ latitude1, $ longitude1, $ latitude2, $ longitude2) {$ earth_radius = 6371000; // approximate radius of earth in meters $ dLat = deg 2rad ($ latitude2-$ latitude1 ); $ dLon = deg 2rad ($ longitude2-$ longitude1);/* Using the Haversine formula http://en.wiki Pedia.org/wiki/Haversine_formula http://www.codecodex.com/wiki/Calculate_Distance_Between_Two_Points_on_a_Globe verification: Baidu map http://developer.baidu.com/map/jsdemo.htm#a6_1 calculate the distance */$ a = sin ($ dLat/2) * sin ($ dLat/2) + cos (deg 2rad ($ latitude1 )) * cos (deg 2rad ($ latitude2) * sin ($ dLon/2) * sin ($ dLon/2 ); $ c = 2 * asin (sqrt ($ a); $ d = $ earth_radius * $ c; return round ($ d); // rounding}?>

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.