<?xml version="1.0" encoding="UTF-8" ?>
<rdf:RDF
  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  xmlns="http://purl.org/rss/1.0/"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:content="http://purl.org/rss/1.0/modules/content/">

  <channel rdf:about="http://mtcn.ko-me.com/RSS/100/">
    <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/" />
    <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" />
    <description>とりあえずPHP</description>
    <dc:language>ja</dc:language>
    <dc:date>2010-01-14T14:06:54+09:00</dc:date>
    <items>
    <rdf:Seq>
      <rdf:li rdf:resource="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" />
    </rdf:Seq>
    </items>
  </channel>

  <item rdf:about="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>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>
    <title>Geohash関数</title>
    <description>Geohashエンコード、デコード関数を書いてみた。
Geohash文字列を緯度と経度の区間に変換：geohash_decode_interval
Geohash文字列を緯度と経度に変換：geohash_decode
緯度と経度をGeohash文字列に変換：geohash_eｎcode
Ge...</description>
    <content:encoded><![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 />]]></content:encoded>
    <dc:subject>関数、ライブラリ</dc:subject>
    <dc:date>2010-01-14T14:07:59+09:00</dc:date>
    <dc:creator>No Name Ninja</dc:creator>
    <dc:publisher>NINJA BLOG</dc:publisher>
    <dc:rights>No Name Ninja</dc:rights>
  </item>
</rdf:RDF>
