<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:blogChannel="http://backend.userland.com/blogChannelModule" >
  <channel>
  <title>とりあえずPHP</title>
  <link>http://mtcn.ko-me.com/</link>
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://mtcn.ko-me.com/RSS/" />
  <description>とりあえずPHP</description>
  <lastBuildDate>Thu, 14 Jan 2010 05:06:54 GMT</lastBuildDate>
  <language>ja</language>
  <copyright>© Ninja Tools Inc.</copyright>
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" />

    <item>
    <title>Geohash関数</title>
    <description>
    <![CDATA[Geohashエンコード、デコード関数を書いてみた。<br />
Geohash文字列を緯度と経度の区間に変換：geohash_decode_interval<br />
Geohash文字列を緯度と経度に変換：geohash_decode<br />
緯度と経度をGeohash文字列に変換：geohash_eｎcode<br />
Geohash文字列から、隣接する領域（(2n+1)^2-1個）のGeohash文字列を返す：geohash_neighbour<br />
<br />
//integer to base32<br />
function int_2_base32($v_in){<br />
&nbsp;&nbsp; &nbsp;$v = (int)$v_in;<br />
&nbsp;&nbsp; &nbsp;if($v &lt; 0 || $v &gt; 31) return false;<br />
<br />
&nbsp;&nbsp; &nbsp;$base32 = '0123456789bcdefghjkmnpqrstuvwxyz';<br />
&nbsp;&nbsp; &nbsp;$str = substr($base32, $v, 1);<br />
&nbsp;&nbsp; &nbsp;return $str;<br />
}<br />
<br />
//base32 to integer<br />
function base32_2_int($str_in){<br />
&nbsp;&nbsp; &nbsp;if(strlen($str_in) != 1) return false;<br />
&nbsp;&nbsp; &nbsp;$str = $str_in;<br />
<br />
&nbsp;&nbsp; &nbsp;$base32 = '0123456789bcdefghjkmnpqrstuvwxyz';<br />
&nbsp;&nbsp; &nbsp;$v = strpos($base32, $str);<br />
&nbsp;&nbsp; &nbsp;return $v; // not found: false<br />
}<br />
<br />
//geohash string to intervals of latitude, longitude<br />
function geohash_decode_interval($geohash_in){<br />
&nbsp;&nbsp; &nbsp;$geohash = $geohash_in;<br />
<br />
&nbsp;&nbsp; &nbsp;$ary_lat = array(-90.0, 90.0);<br />
&nbsp;&nbsp; &nbsp;$ary_lon = array(-180.0, 180.0);<br />
&nbsp;&nbsp; &nbsp;$lat_r = 90.0;<br />
&nbsp;&nbsp; &nbsp;$lon_r = 180.0;<br />
<br />
&nbsp;&nbsp; &nbsp;$len = strlen($geohash);<br />
&nbsp;&nbsp; &nbsp;if($len == 0) return false; //error<br />
<br />
&nbsp;&nbsp; &nbsp;$ary_mask = array(16,8,4,2,1);<br />
<br />
&nbsp;&nbsp; &nbsp;$is_even = true;<br />
&nbsp;&nbsp; &nbsp;for($i=0; $i&lt;$len; $i++){<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; $str = substr($geohash, $i, 1);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; $v = base32_2_int($str);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; if($v === false) return false; //error<br />
<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; foreach($ary_mask as $mask){<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if($is_even){<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $lon_r /= 2;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if($v &amp; $mask){<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $ary_lon = array(($ary_lon[0] + $ary_lon[1])/2, $ary_lon[1]);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else{<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $ary_lon = array($ary_lon[0], ($ary_lon[0] + $ary_lon[1])/2);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else{<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $lat_r /= 2;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if($v &amp; $mask){<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $ary_lat = array(($ary_lat[0] + $ary_lat[1])/2, $ary_lat[1]);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else{<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $ary_lat = array($ary_lat[0], ($ary_lat[0] + $ary_lat[1])/2);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $is_even = !$is_even;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp; &nbsp;}<br />
<br />
&nbsp;&nbsp; &nbsp;return array($ary_lat, $ary_lon);<br />
}<br />
<br />
//geohash string to latitude, longitude<br />
function geohash_decode($geohash_in){<br />
&nbsp;&nbsp; &nbsp;$ary_tmp = geohash_decode_interval($geohash_in);<br />
&nbsp;&nbsp; &nbsp;if($ary_tmp == false) return false;<br />
&nbsp;&nbsp; &nbsp;list($ary_lat, $ary_lon) = $ary_tmp;<br />
<br />
&nbsp;&nbsp; &nbsp;$places_lat = max(1, -round(log10($ary_lat[1] - $ary_lat[0]))) - 1;<br />
&nbsp;&nbsp; &nbsp;$places_lon = max(1, -round(log10($ary_lon[1] - $ary_lon[0]))) - 1;<br />
<br />
&nbsp;&nbsp; &nbsp;$lat = round(($ary_lat[0] + $ary_lat[1]) / 2, $places_lat);<br />
&nbsp;&nbsp; &nbsp;$lon = round(($ary_lon[0] + $ary_lon[1]) / 2, $places_lon);<br />
<br />
&nbsp;&nbsp; &nbsp;return array($lat, $lon);<br />
}<br />
<br />
//latitude, longitude to geohash string<br />
function geohash_encode($lat_in, $lon_in, $len_in=11){<br />
&nbsp;&nbsp; &nbsp;$lat = (float)$lat_in;<br />
&nbsp;&nbsp; &nbsp;$lon = (float)$lon_in;<br />
&nbsp;&nbsp; &nbsp;if($lat &lt; -90 || $lat &gt; 90 || $lon &lt; -180 || $lon &gt; 180) return false;<br />
<br />
&nbsp;&nbsp; &nbsp;$len = (int)$len_in;<br />
&nbsp;&nbsp; &nbsp;if($len &lt;= 0) return false;<br />
<br />
&nbsp;&nbsp; &nbsp;$ary_lat = array(-90.0, 90.0);<br />
&nbsp;&nbsp; &nbsp;$ary_lon = array(-180.0, 180.0);<br />
<br />
&nbsp;&nbsp; &nbsp;$cnt = 0;<br />
&nbsp;&nbsp; &nbsp;$str_bin = &quot;&quot;;<br />
&nbsp;&nbsp; &nbsp;while($cnt &lt;= $len * 5){<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; $lon_c = ($ary_lon[0] + $ary_lon[1]) / 2;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; if($lon &lt; $lon_c){<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $str_bin .= &quot;0&quot;;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $ary_lon[1] = $lon_c;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; else{<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $str_bin .= &quot;1&quot;;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $ary_lon[0] = $lon_c;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; $lat_c = ($ary_lat[0] + $ary_lat[1]) / 2;<br />
<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; if($lat &lt; $lat_c){<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $str_bin .= &quot;0&quot;;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $ary_lat[1] = $lat_c;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; else{<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $str_bin .= &quot;1&quot;;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $ary_lat[0] = $lat_c;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; $cnt++;<br />
&nbsp;&nbsp; &nbsp;}<br />
<br />
&nbsp;&nbsp; &nbsp;$str_geohash = &quot;&quot;;<br />
&nbsp;&nbsp; &nbsp;for($i=0; $i&lt;$len; $i++){<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; $str_sub = substr($str_bin, $i*5, 5);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; $str_geohash .= int_2_base32(bindec($str_sub));<br />
&nbsp;&nbsp; &nbsp;}<br />
<br />
&nbsp;&nbsp; &nbsp;return $str_geohash;<br />
}<br />
<br />
//return geohash strings of neighbours<br />
function geohash_neighbour($geohash_in, $range_in=1){<br />
&nbsp;&nbsp;&nbsp; $geohash = $geohash_in;<br />
&nbsp;&nbsp;&nbsp; $len = strlen($geohash);<br />
<br />
&nbsp;&nbsp;&nbsp; $range = (int)$range_in;<br />
&nbsp;&nbsp;&nbsp; if($range &lt; 1) return false; //error<br />
<br />
&nbsp;&nbsp;&nbsp; $ary_tmp = geohash_decode_interval($geohash);<br />
&nbsp;&nbsp;&nbsp; if($ary_tmp == false) return false; //error<br />
<br />
&nbsp;&nbsp;&nbsp; list($ary_lat, $ary_lon) = $ary_tmp;<br />
&nbsp;&nbsp;&nbsp; $delta_lat = $ary_lat[1] - $ary_lat[0];<br />
&nbsp;&nbsp;&nbsp; $delta_lon = $ary_lon[1] - $ary_lon[0];<br />
&nbsp;&nbsp;&nbsp; $lat = ($ary_lat[0] + $ary_lat[1]) / 2;<br />
&nbsp;&nbsp;&nbsp; $lon = ($ary_lon[0] + $ary_lon[1]) / 2;<br />
<br />
&nbsp;&nbsp;&nbsp; $ary_geohash = array();<br />
&nbsp;&nbsp;&nbsp; for($i=-1*$range; $i&lt;=1*$range; $i++){<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for($j=-1*$range; $j&lt;=1*$range; $j++){<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if($i == 0 &amp;&amp; $j == 0) continue;<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $lat_tmp = $lat + $delta_lat * $i;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if($lat_tmp &lt; -90.0) $lat_tmp += 180.0;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else if($lat_tmp &gt; 90.0) $lat_tmp -= 180.0;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $lon_tmp = $lon + $delta_lon * $j;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if($lon_tmp &lt; -180.0) $lon_tmp += 360.0;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else if($lon_tmp &gt; 180.0) $lon_tmp -= 360.0;<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $str_tmp = geohash_encode($lat_tmp, $lon_tmp, $len);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if($str_tmp == false) return false; //error<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $ary_geohash[] = $str_tmp;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp; &nbsp;return $ary_geohash;<br />
}<blockquote> </blockquote> <br />
参考：<br />
<a href="http://blog.masuidrive.jp/index.php/2010/01/13/geohash/trackback/">http://blog.masuidrive.jp/index.php/2010/01/13/geohash/trackback/</a><br />
<a href="http://en.wikipedia.org/wiki/Geohash">http://en.wikipedia.org/wiki/Geohash</a><br />
<br />
ベタベタな書き方ですが・・・<br />
<br />
<br />]]>
    </description>
    <category>関数、ライブラリ</category>
    <link>http://mtcn.ko-me.com/%E9%96%A2%E6%95%B0%E3%80%81%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA/geohash%E9%96%A2%E6%95%B0</link>
    <pubDate>Thu, 14 Jan 2010 05:07:59 GMT</pubDate>
    <guid isPermaLink="false">mtcn.ko-me.com://entry/1</guid>
  </item>

    </channel>
</rss>