<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
		xmlns:xhtml="http://www.w3.org/1999/xhtml"
>

<channel>
	<title>クレコ &#187; PHP</title>
	<atom:link href="http://creco.net/tag/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://creco.net</link>
	<description>East or west, home is best.</description>
	<lastBuildDate>Fri, 27 Nov 2009 13:26:56 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://creco.net/tag/php/feed/" />
		<item>
		<title>投稿スラッグをGoogle AJAX Language APIで英訳するWordPressのプラグインを作った</title>
		<link>http://creco.net/2009/06/14/made_a_wordpress_plugin_that_translate_post-slug_with_google_ajax_language_api/</link>
		<comments>http://creco.net/2009/06/14/made_a_wordpress_plugin_that_translate_post-slug_with_google_ajax_language_api/#comments</comments>
		<pubDate>Sat, 13 Jun 2009 17:54:58 +0000</pubDate>
		<dc:creator>inagaki</dc:creator>
				<category><![CDATA[作ってみた]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://creco.net/?p=553</guid>
		<description><![CDATA[ 
それは、どういうものですか？
WordPressのURLとして使われる投稿スラッグ。これは、標準だと投稿タイトルをURLエンコードしたものが自動的に使われて、やけに長くなるしかっこ悪い。
んで、ぼくは投稿タイトルを逐 [...]]]></description>
			<content:encoded><![CDATA[<p><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="投稿スラッグをGoogle AJAX Language APIで英訳するWordPressのプラグインを作った" border="0" alt="投稿スラッグをGoogle AJAX Language APIで英訳するWordPressのプラグインを作った" src="http://creco.net/wp-content/uploads/Ci090614030747.jpg" width="440" height="257" /> </p>
<h4>それは、どういうものですか？</h4>
<p>WordPressのURLとして使われる<strong>投稿スラッグ</strong>。これは、標準だと投稿タイトルをURLエンコードしたものが自動的に使われて、やけに長くなるしかっこ悪い。</p>
<p>んで、ぼくは投稿タイトルを逐一英訳して投稿スラッグとして入力しているんだけど、ボキャ貧なので通じるかどうかわからない怪しげな英語になってしまう ＞＜</p>
<p>そこで、自動的に投稿タイトルを英訳してくれて、それが投稿スラッグになってくれると素敵だなと思い、WordPressのプラグインを作ってみました。</p>
<p> <span id="more-553"></span><br />
<h4>インストール方法と使い方</h4>
<pre class="csharpcode">&lt;?php
<span class="rem">/*</span>
<span class="rem">Plugin Name: Slug translate J to E </span>
<span class="rem">Plugin URI: http://creco.net/</span>
<span class="rem">Description: 投稿タイトルの日本語をそのまま投稿スラッグにするのではなく、Google AJAX Language APIで英訳したものを投稿スラッグにします</span>
<span class="rem">Author: Shintaro Inagaki</span>
<span class="rem">Version: 1.0</span>
<span class="rem">Author URI: http://creco.net/</span>
<span class="rem">*/</span>

function slug_translate_j_to_e($title) {

    $translateApiUrl = <span class="str">'http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&amp;q='</span>.urlencode($title).<span class="str">'&amp;langpair=ja%7Cen'</span>;
    $response = file_get_contents($translateApiUrl);  

    $parsedJson = json_decode($response);

    <span class="kwrd">if</span>(isset($parsedJson-&gt;responseData-&gt;translatedText)) {
        $title = $parsedJson-&gt;responseData-&gt;translatedText;
    }
    $title = strtolower($title);
    $title = str_replace(<span class="str">' '</span>, <span class="str">'_'</span>, $title);
    $title = preg_replace(<span class="str">'/[^%a-z0-9_-]/'</span>, <span class="str">''</span>, $title);

    <span class="kwrd">return</span> $title;
}

add_filter(<span class="str">'sanitize_title'</span>, <span class="str">'slug_translate_j_to_e'</span>, 9);

?&gt;</pre>
<p>上のコードを適当なファイルに保存（ slug-translate-j-to-e.php とか適当な名前つけてね）して、WordPressのプラグインフォルダ（ /wp-content/plugins/ 以下）にアップロードすれば、プラグイン管理画面から「使用する」が選べるようになります。</p>
<p>後は、普通に投稿すれば自動的に投稿タイトルを翻訳したものが投稿スラッグとして使われてると思います。</p>
<p>翻訳を確認したいという場合は、「下書きとして保存」とし、その後に投稿スラッグを編集すれば、半手動で利用できるかと。</p>
<h4>やっていること<br />
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
</h4>
<p><a href="http://code.google.com/intl/ja/apis/ajaxlanguage/documentation/reference.html">Translation API のクラス リファレンス &#8211; Google AJAX Language API &#8211; Google Code</a> をRESTで使用しています。</p>
<p>タイトルをAPIに投げて、JSONで帰ってきたものを処理。</p>
<p>処理は、上から順番に、大文字を小文字にする → スペースをアンダースコアに変換する → 小文字英数字とハイフン、アンダースコア以外の文字を削除する といった内容。</p>
<h4>注意点</h4>
<p>Google の翻訳は期待しないほうがいい。</p>
]]></content:encoded>
			<wfw:commentRss>http://creco.net/2009/06/14/made_a_wordpress_plugin_that_translate_post-slug_with_google_ajax_language_api/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://creco.net/2009/06/14/made_a_wordpress_plugin_that_translate_post-slug_with_google_ajax_language_api/" />
	</item>
		<item>
		<title>Googleの逆ジオコーディングをためしてみた</title>
		<link>http://creco.net/2009/03/07/implement_google_reverse_geocoding_api/</link>
		<comments>http://creco.net/2009/03/07/implement_google_reverse_geocoding_api/#comments</comments>
		<pubDate>Sat, 07 Mar 2009 03:37:15 +0000</pubDate>
		<dc:creator>inagaki</dc:creator>
				<category><![CDATA[日記]]></category>
		<category><![CDATA[Google Maps]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[逆ジオコーディング]]></category>

		<guid isPermaLink="false">http://creco.net/2009/03/07/implement_google_reverse_geocoding_api/</guid>
		<description><![CDATA[ジオポの地図表示で住所を出したかったので逆ジオコーディング（緯度・経度から住所を取り出すこと）をGoogleのAPI使ってやってみました。
まず基本
Google MapsのAPIと違って、日本語での情報が少ない（マニュ [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://geopo.at/" target="_blank">ジオポ</a>の地図表示で住所を出したかったので逆ジオコーディング（緯度・経度から住所を取り出すこと）をGoogleのAPI使ってやってみました。</p>
<h4>まず基本</h4>
<p>Google MapsのAPIと違って、日本語での情報が少ない（<a href="http://code.google.com/intl/en/apis/maps/documentation/geocoding/index.html" target="_blank">マニュアル</a>）けど、</p>
<p>http://maps.google.com/maps/geo?ll=35,135&amp;output=xml&amp;key=GOOGLE_MAPS_API_KEY&amp;hl=ja&amp;oe=UTF8</p>
<p>URLはこのサンプルみたいにして、HTTP GETでXMLが取得できる。</p>
<h5>リクエストパラメーター</h5>
<table cellspacing="0" cellpadding="2" width="400" border="0">
<tbody>
<tr>
<td valign="top" width="49">ll</td>
<td valign="top" width="459">緯度・経度（qでもいいと思う。違いがわからないよ＞＜）</td>
</tr>
<tr>
<td valign="top" width="49">output</td>
<td valign="top" width="459">xml、kml、cvs、json</td>
</tr>
<tr>
<td valign="top" width="49">key</td>
<td valign="top" width="459">Google maps APIキー</td>
</tr>
<tr>
<td valign="top" width="49">hl</td>
<td valign="top" width="459">言語（日本語だとja、英語ならen）。住所記述方法にも影響</td>
</tr>
<tr>
<td valign="top" width="49">oe</td>
<td valign="top" width="459">文字エンコード</td>
</tr>
</tbody>
</table>
<h5>レスポンス（XMLをsimple_xmlでパースした場合）</h5>
<table cellspacing="0" cellpadding="2" width="400" border="0">
<tbody>
<tr>
<td valign="top" width="200">$parsed_xml         <br />-&gt;Response-&gt;Status-&gt;code</td>
<td valign="top" width="200">ステータスコード</td>
</tr>
<tr>
<td valign="top" width="200">$parsed_xml         <br />-&gt;Response-&gt;Placemark</td>
<td valign="top" width="200">Arrayで結果が複数入る</td>
</tr>
<tr>
<td valign="top" width="200">以下 Placemark[0]が親とする</td>
<td valign="top" width="200">&#160;</td>
</tr>
<tr>
<td valign="top" width="200">AddressDetails['Accuracy']</td>
<td valign="top" width="200">精度。後述</td>
</tr>
<tr>
<td valign="top" width="200">address</td>
<td valign="top" width="200">住所。言語によって記述方法が変化。日本語だと[県][市][町] って具合だけど、英語だと [Street], [City], [Prefecture]          <br />あと、住所には国名が含まれる。</td>
</tr>
<tr>
<td valign="top" width="200">AddressDetails-&gt;Country         <br />-&gt;CountryNameCode</td>
<td valign="top" width="200">国のコード。JP</td>
</tr>
<tr>
<td valign="top" width="200">AddressDetails-&gt;Country         <br />-&gt;CountryName</td>
<td valign="top" width="200">日本</td>
</tr>
<tr>
<td valign="top" width="200">AddressDetails-&gt;Country         <br />-&gt;AdministrativeArea          <br />-&gt;AdministrativeAreaName</td>
<td valign="top" width="200">東京都</td>
</tr>
<tr>
<td valign="top" width="200">AddressDetails-&gt;Country         <br />-&gt;AdministrativeArea          <br />-&gt;Locality          <br />-&gt;LocalityName</td>
<td valign="top" width="200">渋谷区</td>
</tr>
<tr>
<td valign="top" width="200">AddressDetails-&gt;Country         <br />-&gt;AdministrativeArea          <br />-&gt;Locality          <br />-&gt;DependentLocality          <br />-&gt;DependentLocalityName</td>
<td valign="top" width="200">渋谷</td>
</tr>
<tr>
<td valign="top" width="200">AddressDetails-&gt;Country         <br />-&gt;AdministrativeArea          <br />-&gt;Locality          <br />-&gt;DependentLocality          <br />-&gt;Thoroughfare          <br />-&gt;ThoroughfareName</td>
<td valign="top" width="200">１丁目２６</td>
</tr>
<tr>
<td valign="top" width="200">AddressDetails-&gt;Country         <br />-&gt;AdministrativeArea          <br />-&gt;Locality          <br />-&gt;DependentLocality          <br />-&gt;PostalCode          <br />-&gt;PostalCodeNumber</td>
<td valign="top" width="200">日本だと取れない。アメリカだけかな？</td>
</tr>
</tbody>
</table>
<p>基本的に詳細な住所ほど、先頭にくるのでPlacemark[0]を見れればokとか考えていたらハマった。</p>
<p> <span id="more-149"></span><br />
<h4>なぜか道路の名前を返す、素敵なリバースジオコーダ－</h4>
<p>ときどき、住所がとれなくて変だな？っておもってよくみると「国道１号」みたいに道の名前が配列の先頭にきてた。他にも郵便番号がとれたりする。</p>
<p>そんな道の名前なんか知りたくないので、どうするかというと、<strong>Accuracy</strong>で判別してやる。</p>
<h5>Accuracy</h5>
<table cellspacing="0" cellpadding="2" width="400" border="0">
<tbody>
<tr>
<td valign="top" width="200">精度値</td>
<td valign="top" width="200">説明</td>
</tr>
<tr>
<td valign="top" width="200">0</td>
<td valign="top" width="200">どこそこ</td>
</tr>
<tr>
<td valign="top" width="200">1</td>
<td valign="top" width="200">国レベル</td>
</tr>
<tr>
<td valign="top" width="200">2</td>
<td valign="top" width="200">州、都道府県レベル</td>
</tr>
<tr>
<td valign="top" width="200">3</td>
<td valign="top" width="200">カウンティレベル</td>
</tr>
<tr>
<td valign="top" width="200">4</td>
<td valign="top" width="200">市町村レベル</td>
</tr>
<tr>
<td valign="top" width="200">5</td>
<td valign="top" width="200">郵便番号レベル</td>
</tr>
<tr>
<td valign="top" width="200">6</td>
<td valign="top" width="200">道レベル</td>
</tr>
<tr>
<td valign="top" width="200">7</td>
<td valign="top" width="200">交差点レベル</td>
</tr>
<tr>
<td valign="top" width="200">8</td>
<td valign="top" width="200">街区レベル</td>
</tr>
<tr>
<td valign="top" width="200">9</td>
<td valign="top" width="200">ビル名、店名</td>
</tr>
</tbody>
</table>
<p>つまり、Accuracyが5とか6のはいらない子なので、ループ回してcontinueとかでスキップすればいい。</p>
<p>これだけに注意しておけば、世界中の逆ジオコーディングがお手軽にできるので、Google APIはとっても魅力的。あと、住所ってそんなに頻繁に変わらないのでキャッシュしておくのは必須かと。</p>
<p>僕は、多言語対応させるために、ジオポコード（バイナリvarcharに注意）と言語をキーにしてキャッシュするようにしました。    <br />住所の記述方法の切り分けは、日本式がそのままくっつける、アメリカ式は反転してから&#8217;, &#8216;をつけて生成みたいな形。</p>
</p>
<div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:e4bbf1fb-60b1-4b13-805f-7c942ecc08be" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
<pre name="code" class="php">		$address = array ();
		if ($location['scale'] &gt;= 6) {
			$address[] = $reverse_geocode['administrative_area_name'];
			$address[] = $reverse_geocode['locality_name'];
			$address[] = $reverse_geocode['dependent_locality_name'];
			$address[] = $reverse_geocode['thoroughfare_name'];
		}
		elseif ($location['scale'] &gt;= 4) {
			$address[] = $reverse_geocode['administrative_area_name'];
			$address[] = $reverse_geocode['locality_name'];
			$address[] = $reverse_geocode['dependent_locality_name'];
		}
		elseif ($location['scale'] &gt;= 2) {
			$address[] = $reverse_geocode['administrative_area_name'];
			$address[] = $reverse_geocode['locality_name'];
		} else {
			$address[] = $reverse_geocode['administrative_area_name'];
		}
		// 日本式とアメリカ式の住所表記
		if ($this-&gt;config-&gt;item('language_min') == 'ja') {
			$result = implode($address);
		} else {
			$address = array_reverse($address);
			$result = implode(', ', $address);
		}</pre>
</div>
<p>ソースにすると&#8593;。ジオポの縮尺が曖昧になっていく度に、住所も曖昧になる。</p>
]]></content:encoded>
			<wfw:commentRss>http://creco.net/2009/03/07/implement_google_reverse_geocoding_api/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://creco.net/2009/03/07/implement_google_reverse_geocoding_api/" />
	</item>
		<item>
		<title>ジオポの符号化、復号化をいろんな言語で書いてみる</title>
		<link>http://creco.net/2009/03/05/write_codes_in_variaous_languages/</link>
		<comments>http://creco.net/2009/03/05/write_codes_in_variaous_languages/#comments</comments>
		<pubDate>Thu, 05 Mar 2009 08:55:22 +0000</pubDate>
		<dc:creator>inagaki</dc:creator>
				<category><![CDATA[日記]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[エクセル]]></category>
		<category><![CDATA[ジオポ]]></category>

		<guid isPermaLink="false">http://creco.net/2009/03/05/write_codes_in_variaous_languages/</guid>
		<description><![CDATA[位置情報をいくら短縮して色んなことに応用できるといっても、ユーザーが使ってくれるまでの敷居が高い（今のブラウザ経由の符号化じゃ、ダメってこと）とどうしようもない。
そんな理由で、まずはユーザーが接するアプリケーションの開 [...]]]></description>
			<content:encoded><![CDATA[<p>位置情報をいくら短縮して色んなことに応用できるといっても、ユーザーが使ってくれるまでの敷居が高い（今のブラウザ経由の符号化じゃ、ダメってこと）とどうしようもない。</p>
<p>そんな理由で、まずはユーザーが接するアプリケーションの開発者サイドにジオポ実装を働きかけていきたい。そのためにも、具体的なサンプルコードをプログラミング苦手な僕が書いてみた。</p>
<p>と、その前に&#8230;   <br />ジオポが<a href="http://netafull.net/" target="_blank">ネタフル</a>で紹介されたよ！    <br /><a href="http://netafull.net/tech/029580.html" target="_blank">位置情報を短縮したURLに変換するウェブサービス「ジオポ」</a></p>
<p>スクリーンショット付きで丁寧に紹介していただきありがとうございます。モチベーションあがりました！</p>
<p> <span id="more-129"></span><br />
<h4>実装するアルゴリズム</h4>
<p><a href="http://geopo.at/intl/ja/developer/" target="_blank">ジオポ 開発者向け情報</a>にも書いたんだけど、ジオポの符号化はいろんな方法が考えられる。</p>
<p>その中でも、一番わかりやすいと思われる方法を各サンプルコードで実装することにする。</p>
<blockquote><h6>ジオポの符号化の実装</h6>
<p>ジオポの符号化方法ですが、こちらで紹介する方法以外にもアルゴリズム（8進数化してビット演算など）はあると思います。ここでは、一番わかりやすいアルゴリズムを紹介します。また、文字ではわかりにくいと思いますので、実際にいろいろな言語で実装したコードは、<a href="http://geopo.at/intl/ja/developer/#appendix">付録</a>をご覧ください。</p>
<p>変換する緯度・経度は度数法での度（D）表記での数値です。もし、度分（DM）表記や度分秒（DMS）表記の場合は、前もって度へと変換してください。     <br />また、南緯と西経はそれぞれマイナス値となります。 </p>
<p>緯度・経度からジオポへの符号化を実装するには、まず度数法で与えられる緯度・経度を十進数に変換します。     <br />緯度と経度をそれぞれ90と180を足して正の値とします。それから、それぞれ90と180で割り、0から1までの値になります。最後に、8の10乗をかけます。 </p>
<p>続いて、十進数化した緯度・経度がジオポ符号でのどのエリアにあたるかを算出します。     <br />緯度は、8を9から縮尺を引いた回数だけ乗じた数字で割ってやり、さらに、その数値を8で割ったあまりを取り出します。経度も同様に、8を9から縮尺を引いた回数だけ乗じた数字で割ってやり、さらに、その数値を8で割ったあまりを取り出し、経度には8をかけてやります。その2つの数値を足すと0から63の数値となり、それに対応する文字がジオポ符号ということになります。 </p>
<p>次の符号を上のルーチンを繰り返しますが、8を9から縮尺を引いた回数だけ乗じた数字という部分が変化する点に注意してください。この繰り返す回数により、ジオポコードの縮尺（Scale）を決定することができます。 </p>
<h6>復号化（デコード）</h6>
<p>復号化する方法は符号化の逆をすることで実装できます（ジオポコードは可逆性を持ちます）。 </p>
<p>ただし、ジオポは小縮尺にも対応しているため、小縮尺になるほど符号化した位置情報との誤差が大きくなります。その誤差をできるだけ平均にするため、緯度・経度をエリアの代表緯度・経度（エリアの真ん中の緯度・経度）へと変換する式が含まれています。 </p>
<p>ジオポをクライアントソフト側で独自に復号化して緯度・経度を取り出したい場合は、ジオポURLからジオポコードを抽出する必要があります。     <br />下記の正規表現を用いれば、ジオポコードを抽出することができます。 </p>
</blockquote>
<ul>
<li>四則演算</li>
<li>forループ</li>
<li>べき乗、切り捨て、余り の数学関数</li>
<li>文字列の長さ、指定したサイズでの文字列の切り出し、文字列の中にある文字の位置 の文字列関数</li>
</ul>
<p>キーとなる所はこんだけで、各言語にある関数などを言語間の違いに注意して実装してみる。</p>
<h4>実際に実装</h4>
<h5>JavaScript</h5>
<p>
<div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:b44dd511-e4bb-4235-8664-baba02e474ba" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
<pre name="code" class="js">/*
 * GeoPo Encode in JavaScript
 * @author : Shintaro Inagaki
 * @param location (Object)
 * @return geopo (String)
 */
function geopoEncode(location){
	// 64characters (number + big and small letter + hyphen + underscore)
	var chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";

	var geopo = new String();
	var lat = parseFloat(location.lat); // Parse as float
	var lng = parseFloat(location.lng); // Parse as float
	var scale = parseInt(location.scale); // Parse as int

	// Change a degree measure to a decimal number
	lat = (lat + 90) / 180 * Math.pow(8, 10);
	lng = (lng + 180) / 360 * Math.pow(8, 10);

	// Compute a GeoPo code from head and concatenate
	for(var i = 0; i &lt; scale; i++) {
		geopo = geopo + chars.substr(Math.floor(lat / Math.pow(8, 9 - i) % 8) + Math.floor(lng / Math.pow(8, 9 - i) % 8) * 8, 1);
	}
	return geopo;
}

/*
 * GeoPo Decode in JavaScript
 * @author : Shintaro Inagaki
 * @param geopo (String)
 * @return location (Object)
 */
function geopoDecode(geopo){
	// 64characters (number + big and small letter + hyphen + underscore)
	var chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";

	var location = new Object();
	var lat = 0;
	var lng = 0;
	var scale = geopo.length; // Scale is length of GeoPo code
	var order = 0;

	for (var i = 0; i &lt; scale; i++) {
		// What number of character that equal to a GeoPo code (0-63)
		order = chars.indexOf(geopo.substr(i, 1));
		// Lat/Lng plus geolocation value of scale
		lat = lat + Math.floor(order % 8) * Math.pow(8, 9 - i);
		lng = lng + Math.floor(order / 8) * Math.pow(8, 9 - i);
	}

	// Change a decimal number to a degree measure, and plus revised value that shift center of area
	location.lat = lat * 180 / Math.pow(8, 10) + 180 / Math.pow(8, scale) / 2 - 90;
	location.lng = lng * 360 / Math.pow(8, 10) + 360 / Math.pow(8, scale) / 2 - 180;
	location.scale = scale;

	return location;
}		</pre>
</div>
<p>僕はジオポを最初にJavaScriptで作ったので、いわばこれが原型。</p>
<p>パラメーターがString型でそのまま入ってくるといけないので、最初に<strong>parseFloat()</strong>と<strong>parseInt()</strong>でそれぞれ型を決めてやる。</p>
<p>そして、べき乗には<strong>Math.pow()</strong>、切り捨てには<strong>Math.floor()</strong>という数学関数があるので利用。</p>
<p>文字列。String.<strong>length</strong>は文字の長さ。JavaScriptの文字列の結合は<strong>+</strong>で、String.<strong>substr()</strong>メソッドによって文字列を切り出してやる。文字列の中にある文字の位置を取ってくるのは String.<strong>indexOf()</strong>メソッド。</p>
<p>JavaScriptはTry&amp;Errorがしやすいから、実装の基本にするのに向いてるのかも。amachangさんが言ってたように、ブラウザさえあればどこでもプログラミングできるメリットもあるしね。</p>
<h5>PHP</h5>
<p><div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:6db8bab2-2b9b-497a-8f56-ea95895bede1" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
<pre name="code" class="php">/*
 * GeoPo Encode in PHP
 * @author : Shintaro Inagaki
 * @param $location (Array)
 * @return $geopo (String)
 */
function geopoEncode($location) {
	// 64characters (number + big and small letter + hyphen + underscore)
	$chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";

	$geopo = "";
	$lat = $location['lat'];
	$lng = $location['lng'];
	$scale = $location['scale'];

	// Change a degree measure to a decimal number
	$lat = ($lat + 90) / 180 * pow(8, 10);
	$lng = ($lng + 180) / 360 * pow(8, 10);

	// Compute a GeoPo code from head and concatenate
	for($i = 0; $i &lt; $scale; $i++) {
		$geopo .= substr($chars, floor($lat / pow(8, 9 - $i) % 8) + floor($lng / pow(8, 9 - $i) % 8) * 8, 1);
	}
	return $geopo;
}		

/*
 * GeoPo Decode in PHP
 * @author : Shintaro Inagaki
 * @param $geopo (String)
 * @return $location (Array)
 */
function geopoDecode($geopo) {
	// 64characters (number + big and small letter + hyphen + underscore)
	$chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
	// Array for geolocation
	$location = array ();

	for ($i = 0; $i &lt; strlen($geopo); $i++) {
		// What number of character that equal to a GeoPo code (0-63)
		$order = strpos($chars, substr($geopo, $i, 1));
		// Lat/Lng plus geolocation value of scale
		$location['lat'] = $location['lat'] + floor($order % 8) * pow(8, 9 - $i);
		$location['lng'] = $location['lng'] + floor($order / 8) * pow(8, 9 - $i);
	}

	// Change a decimal number to a degree measure, and plus revised value that shift center of area
	$location['lat'] = $location['lat'] * 180 / pow(8, 10) + 180 / pow(8, strlen($geopo)) / 2 - 90;
	$location['lng'] = $location['lng'] * 360 / pow(8, 10) + 360 / pow(8, strlen($geopo)) / 2 - 180;
	$location['scale'] = strlen($geopo);

	return $location;
}		</pre>
</div>
<p>なんちゃってPerlerからPHPに移行してもう何年も経つけど、やっぱりPHPが好き。未だに知らない関数ばかりだけどね ＞＜</p>
<p>べき乗は<strong>pow()</strong>、切り捨ては<strong>floor()</strong>。文字列の長さは<strong>strlen()</strong>、文字列の切り出しは<strong>substr()</strong>、文字列の中にある文字の位置は<strong>strpos()</strong>。</p>
<p>こういう関数あるかなぁってマニュアル見ると、大抵あるから、CHM形式のマニュアルが手元にあると便利です。</p>
<h5>Objective-C</h5>
<p><div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:d88f016a-8581-4dfd-a40a-333a3c108cad" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
<pre name="code" class="c">/*
 * GeoPo Encode in Objective-C
 * @author : Shintaro Inagaki
 * @param geopo, latitude, longitude, scale (pointer)
 */
-(void)encodeGeopo:(id)geopo latitude:(double *)lat longitude:(double *)lng scale:(int *)scale {
	NSString *chars = @"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";

	*lat = (*lat + 90) / 180 * pow(8.0, 10.0);
	*lng = (*lng + 180) / 360 * pow(8.0, 10.0);

	for(int i = 0; i &lt; *scale; i++){
		[geopo appendString:[chars substringWithRange:NSMakeRange(floor(fmod(*lat / pow(8.0, 9.0 - i), 8.0)) + floor(fmod(*lng / pow(8.0, 9.0 - i), 8.0)) * 8, 1)]];
	}
}		

/*
 * GeoPo Decode in Objective-C
 * @author : Shintaro Inagaki
 * @param geopo, latitude, longitude, scale (pointer)
 */
-(void)decodeGeopo:(id)geopo latitude:(double *)lat longitude:(double *)lng scale:(int *)scale {
	NSString *chars = @"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
	int order;

	*scale = [geopo length];

	for (int i = 0; i &lt; *scale; i++) {
		order = NSMaxRange([chars rangeOfString:[geopo substringWithRange:NSMakeRange(i, 1)]]) - 1;
		*lat += (order % 8) * pow(8, 9 - i);
		*lng += floor(order / 8) * pow(8, 9 - i);
	}

	*lat = *lat * 180 / pow(8, 10) + 180 / pow(8, *scale) / 2 - 90;
	*lng = *lng * 360 / pow(8, 10) + 360 / pow(8, *scale) / 2 - 180;
}		</pre>
</div>
<p>iPhone開発者に媚びを売るにはObjective-Cでの実装も必須だよね。でも、素直にCで書いたほうがよかったかもって後から思った。そんな、ダメダメなサンプルコード。つっこみ歓迎。</p>
<p>パラメーターはポインタで渡す。で、未だに理解できてないけど idやdoubleなどのプリミティブなオブジェクトを使うらしい。</p>
<p>整数のintなら<strong>%</strong>が余りとして利用できるんだけど、doubleなど浮動小数点になると<strong>fmod()</strong>を使わなきゃならん。べき乗の<strong>pow()</strong>の中身も小数点付いてますよってことをアピールしてるんだけど、これって意味あったっけ？（c++の場合はこうじゃないと叱られた気がする）<strong> floor()</strong>で切り捨て。</p>
<p>文字列を切り出すには<strong>substringWithRange:</strong> 使うんだけど、これの引数はNSRange型なので中で<strong>NSMakeRange()</strong>使ってNSRange型を作って渡してやる。そして、文字列をくっつけるには<strong>appendString:</strong>。ただし、こうやって可変な文字列を扱うには文字列の型をNSMutableStringにしないとダメ（ここでいうgeopoの宣言）だから注意してね。</p>
<p>こっからが難問ｗ 復号化のほう</p>
<p>文字列の中にある文字の位置を取ってきたいんだけど、一発でできるようなものはなかった＞＜<br />
  <br />仕方がないので、<strong>substringWithRange:</strong>で文字列を切り出してやって、それがどこの位置かを<strong>rangeOfString:</strong>で取り出すという二段構成に。ただ、それだけだとNSRange型が返ってきて、希望するintではないから<strong>NSMaxRange()</strong>で整数値にするという三段構成に。そうすると、先頭からの位置+1になり、帳尻をあわせるために最後に-1。</p>
<p>ひょっとすると、もっと簡単にサクッとできるような関数があるのかもしれない。あったら教えてくださいな。</p>
<p>しっかし、Objective-Cと他の言語を混ぜて考えると関数の形で混乱するわｗ<br />
  <br />iPhoneアプリ作りは、ゆっくりとした休日にやろうと思った。</p>
<h5>エクセル</h5>
<div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:9dcd44c9-7919-4681-97c3-2a1051d16443" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
<pre name="code" class="xml">
ジオポのエンコード方法（エクセル関数）

以下で利用している【】はセルの位置です（A1、B4等）。各自読み替えて利用してください。

緯度を入力するセルの位置を【緯度】とします。
経度を入力するセルの位置を【経度】とします。
符号化に使用する文字列のあるセルを【符号】とし、
「0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_」
を入力します（「」は除いてください）。

ジオポコードの1文字目を出力したいセルに、
「=MID(【符号】,INT(MOD((【緯度】+90)/180*POWER(8,10)/POWER(8,9),8))+INT(MOD((【経度】+180)/360*POWER(8,10)/POWER(8,9),8))*8+1,1)」
とすると、1文字目のジオポコードが得られます。
同様に、
「=MID(【符号】,INT(MOD((【緯度】+90)/180*POWER(8,10)/POWER(8,8),8))+INT(MOD((【経度】+180)/360*POWER(8,10)/POWER(8,8),8))*8+1,1)」
とPOWERの2番目の引数を1引いてやると、2文字目のジオポコードとなり、2文字目以降も同じ繰り返しとなります。

それぞれのジオポコードのセルを&amp;で結合してやれば、ジオポコードの文字列となります。

（例）
A1に緯度、B1に経度、C1に符号化文字列を入力。
A2に「=MID(C1,INT(MOD((A1+90)/180*POWER(8,10)/POWER(8,9),8))+INT(MOD((B1+180)/360*POWER(8,10)/POWER(8,9),8))*8+1,1)」と入力。
B2に「=MID(C1,INT(MOD((A1+90)/180*POWER(8,10)/POWER(8,8),8))+INT(MOD((B1+180)/360*POWER(8,10)/POWER(8,8),8))*8+1,1)」と入力。
C2に「=MID(C1,INT(MOD((A1+90)/180*POWER(8,10)/POWER(8,7),8))+INT(MOD((B1+180)/360*POWER(8,10)/POWER(8,7),8))*8+1,1)」と入力。
D2に「=MID(C1,INT(MOD((A1+90)/180*POWER(8,10)/POWER(8,6),8))+INT(MOD((B1+180)/360*POWER(8,10)/POWER(8,6),8))*8+1,1)」と入力。
E2に「=MID(C1,INT(MOD((A1+90)/180*POWER(8,10)/POWER(8,5),8))+INT(MOD((B1+180)/360*POWER(8,10)/POWER(8,5),8))*8+1,1)」と入力。
F2に「=MID(C1,INT(MOD((A1+90)/180*POWER(8,10)/POWER(8,4),8))+INT(MOD((B1+180)/360*POWER(8,10)/POWER(8,4),8))*8+1,1)」と入力。
A3に「=A2&amp;B2&amp;C2&amp;D2&amp;E2&amp;F2」と入力すれば、A3で6文字のジオポコードが得られます。
		</pre>
</div>
<p>最後にネタ的なエクセル関数を使った実装。</p>
<p>型の宣言しないで計算できるし好き。べき乗は<strong>POWER()</strong>、切り捨ては<strong>INT()</strong>、余りは<strong>MOD()</strong>。</p>
<p>そして、<strong>MID()</strong>は指定した範囲の文字列を取ってこれて、文字を結合するには<strong>&amp;</strong>で繋げるだけ。</p>
<p>無駄が多くて関数が長くなったり、途中計算用のセルが必要になったりするけど、単純なエクセル関数でも実装できるってことが重要。Scale（縮尺）がないけど気にしない。</p>
<h4>まとめ</h4>
<p>簡単に実装できることを実証したかったんだけど、Objective-Cは時間がかかって気づいたら朝になってた&#8230;</p>
<p>いろんな言語に触れてみるのは楽しいね。今度は、C、Perl、Pythonあたりを挑戦してみるつもり。</p>
]]></content:encoded>
			<wfw:commentRss>http://creco.net/2009/03/05/write_codes_in_variaous_languages/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://creco.net/2009/03/05/write_codes_in_variaous_languages/" />
	</item>
		<item>
		<title>検索エンジンに対応した多言語化方法</title>
		<link>http://creco.net/2009/03/02/internationalization_for_search_engine_crawl/</link>
		<comments>http://creco.net/2009/03/02/internationalization_for_search_engine_crawl/#comments</comments>
		<pubDate>Mon, 02 Mar 2009 09:40:17 +0000</pubDate>
		<dc:creator>inagaki</dc:creator>
				<category><![CDATA[日記]]></category>
		<category><![CDATA[CodeIgniter]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[多言語化]]></category>
		<category><![CDATA[検索エンジン]]></category>

		<guid isPermaLink="false">http://creco.net/2009/03/02/internationalization_for_search_engine_crawl/</guid>
		<description><![CDATA[検索エンジン（まぁGoogleなんだけど）って、ひとつのURIに対してひとつの言語にしか対応してないんですね。
そんなわけで、単純に内部で言語を切り替えただけではクロールされる言語がひとつになってしまい、問題になってきま [...]]]></description>
			<content:encoded><![CDATA[<p>検索エンジン（まぁGoogleなんだけど）って、ひとつのURIに対してひとつの言語にしか対応してないんですね。</p>
<p>そんなわけで、単純に内部で言語を切り替えただけではクロールされる言語がひとつになってしまい、問題になってきます。<br />
そこで、多言語に対応したサイトの作り方をメモとして書いておく。</p>
<p><span id="more-126"></span></p>
<h4>有名なウェブサイトはどうなっている？</h4>
<p>多言語化に対応しているウェブサイトなんて沢山あるわけなんだけど、どうやって対応させるかを調査。</p>
<h5>Google</h5>
<p><a href="http://creco.net/wp-content/uploads/20090302-01.jpg" rel="lightbox[126]"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" src="http://creco.net/wp-content/uploads/20090302-01-thumb.jpg" border="0" alt="20090302_01" width="438" height="296" /></a></p>
<p>Googleの場合、ドメイン自体が<br />
<em><a href="http://www.google.com">www.google.com</a><br />
<a href="http://www.google.co.jp">www.google.co.jp</a></em><br />
と２つあり、<a href="http://www.google.com/intl/ja/">www.google.com/intl/ja/</a> と <a href="http://www.google.co.jp">www.google.co.jp</a> がほとんど同じような内容で日本語対応コンテンツとなっている。</p>
<p>つまり、 <strong>/intl/ja/</strong> の部分が多言語化に対応させた部分。</p>
<h5>Skype</h5>
<p><a href="http://creco.net/wp-content/uploads/20090302-02.jpg" rel="lightbox[126]"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" src="http://creco.net/wp-content/uploads/20090302-02-thumb.jpg" border="0" alt="20090302_02" width="438" height="296" /></a></p>
<p>Skypeの場合はドメインは <a href="http://www.skype.com">www.skype.com</a> のみ。<br />
そして、日本語対応コンテンツは <a href="http://www.skype.com/intl/ja/welcomeback/">www.skype.com/intl/ja/welcomeback/</a> 。welcomebackを削ってもリダイレクトされるので、Googleと同じく</p>
<p><strong>/intl/ja/</strong> の部分が多言語化に対応させた部分。</p>
<p>２つの事例しか見てないけど、/intl/ja/ のように階層を切って多言語化させるのがよさそう（何より、Googleがやってるんだから、間違いないでしょ！）。</p>
<h6>どうでもいい話</h6>
<p><strong>intl</strong> って今までイニシャライズ（initialize：初期化）の略で、スタートページだから初期化なんだよって勘違いしてた ＞＜</p>
<p>これって、インターナショナライゼーション（internatinalization：国際化）の略なんですね。</p>
<h4>CodeIgniterでの実装例</h4>
<p>内部での言語切り替えが済んでる人は飛ばしてください。</p>
<p>僕のやり方なので、多分はずれたやり方だと思うｗ</p>
<h5>前提：内部の国際化対応</h5>
<div id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:b2084124-502c-4ef0-b478-eeac16f66b5a" class="wlWriterSmartContent" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
<pre class="php">// 国際化
if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) &amp;&amp; ereg('ja', $_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
	$config['language'] = 'japanese';
	$config['language_min'] = 'ja';
}else{
	$config['language'] = 'english';
	$config['language_min'] = 'en';
}</pre>
</div>
<p>こんな形で設定ファイル内でブラウザの <strong>HTTP_ACCEPT_LANGUAGE</strong> を読み取って、言語を設定。</p>
<div id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:d681f373-6909-45e4-9b4a-0dcbda8bc2ac" class="wlWriterSmartContent" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
<pre class="php">$this-&gt;lang-&gt;load('index', $this-&gt;config-&gt;item('language'));</pre>
</div>
<p>コントローラー内で言語ファイルの読み込み。</p>
<div id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:2edfaa9c-2562-4eda-9a9a-319154ccd2df" class="wlWriterSmartContent" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
<pre class="php">&lt;img src="hogehoge_&lt;?=$this-&gt;config-&gt;item('language_min')?&gt;.gif" alt="&lt;?=$this-&gt;lang-&gt;line('index_hogehoge')?&gt;" /&gt;</pre>
</div>
<p>ビューでは、前で設定した言語略称（language_min）を利用したファイル名の切り分けや言語ファイルでのテキスト行の読み込みを行います。</p>
<p>言語ファイルは、 /application/language/【言語名】/【言語ファイル名】_lang.php みたいな形で言語の数だけ作成します。</p>
<p>これだけだと、URIはひとつなので、次にroutes.phpを使った切り替え。</p>
<h5>routes.phpを使った言語の切り替え</h5>
<div id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:f58b901f-ecd3-4fba-90af-f75966a2919e" class="wlWriterSmartContent" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
<pre class="php">$route['intl/([a-z]{2})'] = "【class】/【function】/$1";</pre>
</div>
<p>毎度便利なroutes.php。こんだけでok。</p>
<p>functionはデフォルトコントローラーを使って、</p>
<div id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:99c5b6de-0c79-4f75-9719-fe8fe95fa544" class="wlWriterSmartContent" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
<pre class="php">	function index($language = "") {
		// 設定
		switch ($language){
			case 'ja':
				$this-&gt;config-&gt;set_item('language', 'japanese');
				$this-&gt;config-&gt;set_item('language_min', 'ja');
				break;
			case 'en':
				$this-&gt;config-&gt;set_item('language', 'english');
				$this-&gt;config-&gt;set_item('language_min', 'en');
				break;
		}
		$this-&gt;lang-&gt;load('index', $this-&gt;config-&gt;item('language'));</pre>
</div>
<p>みたいに、設定をコントローラーで強制的に上書きしちゃえばいいんじゃないかな。</p>
<h5>最後に、</h5>
<p>手動でも言語を切り替えできるようなリンクをビューに用意してあげて、あとは検索エンジンにうまくクロールされるのを待つだけ。</p>
<p>でも、ソーシャルブックマークのリンクの固定リンクをどこに設定するとか、ルートURLの言語は何にするとかは悩むところですね。</p>
]]></content:encoded>
			<wfw:commentRss>http://creco.net/2009/03/02/internationalization_for_search_engine_crawl/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://creco.net/2009/03/02/internationalization_for_search_engine_crawl/" />
	</item>
		<item>
		<title>CodeIgniterのURIルーティングで.htaccessいらず</title>
		<link>http://creco.net/2009/02/26/i_love_codeigniters_uri_routing/</link>
		<comments>http://creco.net/2009/02/26/i_love_codeigniters_uri_routing/#comments</comments>
		<pubDate>Thu, 26 Feb 2009 13:19:07 +0000</pubDate>
		<dc:creator>inagaki</dc:creator>
				<category><![CDATA[日記]]></category>
		<category><![CDATA[CodeIgniter]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://creco.net/2009/02/26/i_love_codeigniters_uri_routing/</guid>
		<description><![CDATA[とりあえず、開発スピードを優先させるためにフルスクラッチで作ってたジオポですけど、これから、国際化対応させたり、DB使う場面が出てくると思うので、PHPのフレームワーク CodeIgniterに変換した。
フルスクラッチ [...]]]></description>
			<content:encoded><![CDATA[<p>とりあえず、開発スピードを優先させるためにフルスクラッチで作ってたジオポですけど、これから、国際化対応させたり、DB使う場面が出てくると思うので、PHPのフレームワーク CodeIgniterに変換した。</p>
<p>フルスクラッチは、コントローラーからビューだけをinclude()する方法で作っていたので、置き換えもスムース。そして、スピーディー。</p>
<ol>
<li><a href="http://codeigniter.com/">CodeIgniter</a>をダウンロード、展開</li>
<li>.htaccess 書き換え</li>
<li>config.php の設定</li>
<ul>
<li><em>$config['base_url']&#160;&#160;&#160; = &quot;http://&quot; . $_SERVER[&quot;HTTP_HOST&quot;];</em> としてローカル環境・本番環境でも切り替え必要なし。</li>
<li><em>//$config['index_page'] = &quot;index.php&quot;;</em> コメントアウト</li>
</ul>
<li>autoload.php の設定</li>
<ul>
<li>ライブラリのuser_agentとコンフィグに独自config</li>
</ul>
<li>コントローラーをクラス化してやり、少しの書き換え</li>
<li>同時に独自configファイルを作ってやる</li>
<ul>
<li>サーバ名を見て、ローカルだったらデバッグフラグ立てる</li>
<li>Google Maps APIがローカルだと使えない（localhostならいけるけど、プロジェクトごとに projectName.localhostとしてhostsの変更してるので&#8230;）</li>
</ul>
<li>ビューを配置</li>
<li>user_agents.php の書き換え</li>
<ul>
<li>日本向けの携帯設定と、iPhone判別を追加</li>
</ul>
</ol>
<p>こんだけです。多分、1時間もかかってないんじゃないかな？</p>
<h5>気づいたこと&#8594;routes.phpが素敵</h5>
<p>routes.php でクラス、メソッドの呼び出しがマッピングできるんだけど、正規表現が使えるからとっても便利。</p>
<p>今までは、.htaccessでmod_rewriteのために正規表現の条件処理を加えて、パラメータをクエリとして渡してやって、そのクエリをバリデートと分岐させるためにPHPの内部でも正規表現で条件分けしてた。</p>
<p>CodeIgniterだとそんなのいらない、</p>
<p>
<div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:463a41dd-44f4-406a-82aa-1f846d6b9698" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
<pre name="code" class="php">$route['([0-9a-zA-Z_-]{1,10})'] = "geopo/mapGeopo/$1";</pre>
</div>
<p>これだけで完了。記述方法もとってもわかりやすい（たしか、Cakeだともっと複雑だった気が）。</p>
<p>そんなこんなで、これから国際化に向けてがんばろうっと。</p>
<h5>ブログで取り上げてもらった</h5>
<p><a title="ヅラずれなるままに(2009-02-26) - ジオポを試してみた" href="http://www.nilab.info/zurazure/20090226.html">ヅラずれなるままに(2009-02-26) &#8211; ジオポを試してみた</a></p>
<p>書いていただき、ありがとうございます。<br />
  <br />地図からの選択はわかりにくいかな？あのマーカーがドロップしたときの動きが好きで、あんな仕様にしたんだけど、後で変えて試してみっか。</p>
]]></content:encoded>
			<wfw:commentRss>http://creco.net/2009/02/26/i_love_codeigniters_uri_routing/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://creco.net/2009/02/26/i_love_codeigniters_uri_routing/" />
	</item>
		<item>
		<title>ジオポをロカポに対応したよ</title>
		<link>http://creco.net/2009/02/24/geopo_supported_locapoint/</link>
		<comments>http://creco.net/2009/02/24/geopo_supported_locapoint/#comments</comments>
		<pubDate>Tue, 24 Feb 2009 06:20:13 +0000</pubDate>
		<dc:creator>inagaki</dc:creator>
				<category><![CDATA[作ってみた]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[ジオポ]]></category>

		<guid isPermaLink="false">http://creco.net/2009/02/24/geopo_supported_locapoint/</guid>
		<description><![CDATA[ここギコ！さんからロカポ（LocaPoint）に対応するとジオポの欠点を補完できるのでは？とアドバイスをいただいたので対応してみました。
（例） http://geopo.at/SW8.HQ9.CR8.PU8     こ [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://kokogiko.net/">ここギコ！</a>さんからロカポ（LocaPoint）に対応するとジオポの欠点を補完できるのでは？とアドバイスをいただいたので対応してみました。</p>
<p>（例） <a href="http://geopo.at/SW8.HQ9.CR8.PU8">http://geopo.at/SW8.HQ9.CR8.PU8</a>     <br />こんな形で http://geopo.at/ にロカポをくっつけてください。ジオポと同じように、見ている環境に対応した地図を表示させます。</p>
<p> <span id="more-100"></span><br />
<h4>ロカポとは？</h4>
<p><a title="位置情報コード　LocaPoint（ロカポ）" href="http://www.locapoint.com/jp/index.html">位置情報コード LocaPoint（ロカポ）</a></p>
<blockquote><p>ロカポとは、世界中のどんな場所でも12文字で表すことができる、最先端の位置情報コード『LocaPoint』の愛称です。</p>
</blockquote>
<blockquote><p>「今何時？」と聞かれれば「10:35」や「16:45」という短い答えを返せますが、「そこはどこ？」と聞かれると、通常は住所、近くの目印、道順、地図などを使いますが、時刻のように短く答えることはできませんでした。ロカポがあれば、これが可能になります。</p>
</blockquote>
<p>緯度経度って単純な数字の羅列だし、緯度と経度どちらを先に？南北・北西はどうやって表す？などの誰もが理解できる明確なフォーマットというのがないんですよね。</p>
<p>同じ地点でも、DMS（度と分と秒で表す）、DM（度と分で表す）やD（度のみで表す）と表現方法がいくつもあって面倒！でも、Google Mapsが登場してから、D（Google Mapsの方法です）にやっとまとまりつつあるような印象。</p>
<p>ロカポはフォーマットを「英文字・英文字・数字」といった具合に規則性をもたせているので、よくありがちな「Q」と「9」などの聞き間違いによるエラーなどを避けることができるメリットがあります。</p>
<p>ジオポと同じで、位置情報を符号化して圧縮しているので、文字数も12文字と短いよ！</p>
<h4>ジオポをロカポに対応させる</h4>
<h5>ジオポとロカポの判別</h5>
<p>ジオポの場合、.htaccessでmod_writeを使ってパラメータをクエリとして投げてます。</p>
<pre class="csharpcode">RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} \/([0-9a-z_-]{1,10})$ [NC]
RewriteRule ^(.*) /index.php?%1 [L]
RewriteCond %{REQUEST_URI} \/([A-Z]{2}[0-9]\.[A-Z]{2}[0-9]\.[A-Z]{2}[0-9]\.[A-Z]{2}[0-9])$
RewriteRule ^(.*) /index.php?%1 [L]</pre>
<p>上の条件式はジオポので、&quot;0&quot;～&quot;9&quot;と&quot;a&quot;～&quot;z&quot;と&quot;_&quot;と&quot;-&quot;が1から10の連続ってこと。&quot;A&quot;～&quot;Z&quot;が書いてないけど、mod_writeのルールで <strong>[NC]</strong>をつけてやると大文字でも小文字でも構わないってことになるから大丈夫。それらを index.phpに投げてやってるだけ、そんだけ。</p>
<p>下の条件式はロカポので、ロカポのコードフォーマットに合わせた条件式を書いてやり、ジオポと同じように投げてる。ただ、ロカポの場合は[NC]を付けないで大文字しか許可しないようにしてある。後々、内部の処理で小文字を許可した場合、意図しない結果になることを恐れてだ。仕様書には小文字うんぬんの記述が見つからなかったけど、多分ダメなんだろう。</p>
<h5>ロカポのPHP変換関数</h5>
<p>ロカポのサイト内での<a href="http://www.locapoint.com/jp/links.html">リンク</a>に、いろいろな言語で実装されたプログラムがあるんだけど、なぜだかPHPは見つからなかったので、関数を作る。</p>
<p><div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:d0b71221-6a70-497d-9fc6-e5508edb10ee" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
<pre name="code" class="php">/*
 * 【PHP版】ロカポのエンコード
 * @author : Shintaro Inagaki
 * @param $location 位置情報配列
 * @return $locapoint ロカポ
 */
function locapointEncode($location) {

	$locapoint = "";
	$latStep = ($location['lat'] + 90) / 180 * 45697600;
	$lngStep = ($location['lng'] + 180) / 360 * 45697600;

	$locapoint = chr($latStep / 1757600 % 26 + 65) . chr($latStep / 67600 % 26 + 65) . chr($latStep / 6760 % 10 + 48) . '.' . chr($lngStep / 1757600 % 26 + 65) . chr($lngStep / 67600 % 26 + 65) . chr($lngStep / 6760 % 10 + 48) . '.' . chr($latStep / 260 % 26 + 65) . chr($latStep / 10 % 26 + 65) . chr($latStep / 1 % 10 + 48) . '.' . chr($lngStep / 260 % 26 + 65) . chr($lngStep / 10 % 26 + 65) . chr($lngStep / 1 % 10 + 48);

	return $locapoint;
}</pre>
</div>
<p>ロカポのエンコード。</p>
<p>&#160;</p>
<p><div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:aca72bea-156c-48d2-b2b2-b9c9a2647e18" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
<pre name="code" class="php">/*
 * 【PHP版】ロカポのデコード
 * @author : Shintaro Inagaki
 * @param $locapoint ロカポ
 * @return $location 位置情報配列
 */
function locapointDecode($locapoint) {
	// 位置情報配列
	$location = array ();

	$location['lat'] = ((ord(substr($locapoint, 0, 1)) - 65) * 1757600 + (ord(substr($locapoint, 1, 1)) - 65) * 67600 + (ord(substr($locapoint, 2, 1)) - 48) * 6760 + (ord(substr($locapoint, 8, 1)) - 65) * 260 + (ord(substr($locapoint, 9, 1)) - 65) * 10 + (ord(substr($locapoint, 10, 1)) - 48) * 1) * 180 / 45697600 - 90;
	$location['lng'] = ((ord(substr($locapoint, 4, 1)) - 65) * 1757600 + (ord(substr($locapoint, 5, 1)) - 65) * 67600 + (ord(substr($locapoint, 6, 1)) - 48) * 6760 + (ord(substr($locapoint, 12, 1)) - 65) * 260 + (ord(substr($locapoint, 13, 1)) - 65) * 10 + (ord(substr($locapoint, 14, 1)) - 48) * 1) * 360 / 45697600 - 180;

	$location['scale'] = 6; // ロカポのみなら必要ありません

	return $location;
}</pre>
</div>
<p>ロカポのデコード</p>
<p>たぶん、あってると思う。<br />
  <br />さっき、小文字だとおかしくなるって書いてたのは、文字コード表での数値がずれるから。もし、対応させるなら、ロカポに strtoupper()をかませればオッケーです。</p>
<h4>位置情報のコード化について</h4>
<p>ロカポの上田さんの話では、位置情報をコード化させるという事例は海外を含めてもそんなにないそうです。ロカポ、Nコード、マップコード、Natural Area Code(NAC)くらいということ。<br />
  <br />これまで日常で位置情報を扱う機会があまりなかったからかなぁ？でも、これからは位置情報が密接になってくるはず。緯度経度の不便さに気づいたときは、是非これらのコードの活用を検討して欲しいです。</p>
<p>自分用メモとしてそれぞれのサイトにリンク。<br />
  <br />ロカポ：<a title="http://www.locapoint.com/jp/index.html" href="http://www.locapoint.com/jp/index.html">http://www.locapoint.com/jp/index.html</a></p>
<p>Ｎコード：<a title="http://www.ncproject.jp/" href="http://www.ncproject.jp/">http://www.ncproject.jp/</a></p>
<p>マップコード：<a title="http://guide2.e-mapcode.com/" href="http://guide2.e-mapcode.com/">http://guide2.e-mapcode.com/</a></p>
<p>NAC：<a title="http://www.nacgeo.com/" href="http://www.nacgeo.com/">http://www.nacgeo.com/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://creco.net/2009/02/24/geopo_supported_locapoint/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://creco.net/2009/02/24/geopo_supported_locapoint/" />
	</item>
		<item>
		<title>仕事を中断してデブサミに行こう</title>
		<link>http://creco.net/2009/02/16/devsumi2009/</link>
		<comments>http://creco.net/2009/02/16/devsumi2009/#comments</comments>
		<pubDate>Mon, 16 Feb 2009 12:18:26 +0000</pubDate>
		<dc:creator>inagaki</dc:creator>
				<category><![CDATA[イベント・セミナー]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://creco.net/2009/02/16/%e3%83%87%e3%83%96%e3%82%b5%e3%83%9f/</guid>
		<description><![CDATA[
Developers Summit 09 デベロッパーズサミット
会場：目黒雅叙園
主催：株式会社翔泳社
今年も行ってきました、デブサミことデベロッパーズサミット＠目黒。
毎年、毎年、バレンタインと同時開催されるこのイ [...]]]></description>
			<content:encoded><![CDATA[<p><strong><img class="alignnone size-medium wp-image-19" title="デブサミ2009" src="http://creco.net/wp-content/uploads/devsumi2009-300x235.jpg" alt="デブサミ2009" width="300" height="235" /></strong></p>
<p><strong>Developers Summit 09 デベロッパーズサミット</strong><br />
会場：目黒雅叙園<br />
主催：株式会社翔泳社</p>
<p>今年も行ってきました、デブサミことデベロッパーズサミット＠目黒。<br />
毎年、毎年、バレンタインと同時開催されるこのイベントは、日夜システムやソフトの裏側で働くエンジニアが、貴重な時間を割いて貴重なプレゼンをしてくれるという、私にとってはチョコよりも100倍嬉しい贈り物。</p>
<p>セッションごとにさくっと所感（というより走り書き）を。自分メモ。</p>
<p><span id="more-13"></span></p>
<h4>2009年2月12日（木）</h4>
<h5>【12-B-1】 実例で学ぶObjective-C 2.0とGUIの関係～iPhoneアプリ開発を視野に入れて</h5>
<p>荻原剛志 氏</p>
<p>Objective-Cの歴史からだったので、実例部分は少し押し気味だったかな。<br />
MacとiPhoneでは実装方法が少し異なるので、それぞれで簡単なデモ。<br />
デモ見ててXcodeのエディタで右上の□が２つ重なったアイコンをクリックすると、ヘッダと実装ファイルを行き来できることを初めて知った！こういう細かいことは、見に行かないとわからないよね。</p>
<h5>【12-B-2】 iPhone 開発者座談会</h5>
<p>高橋征義 氏/ shachi 氏/ 瀧内元気 氏/ 中川智史 氏/ 森琢磨 氏/ 吉田悠一 氏</p>
<p>豪華なメンバーで、いい意味で普通の方たちでした。中川さんは超イケメン。高橋メソッドで有名な高橋さんがモデレータ。<br />
<a href="http://www.appbank.net/">AppBank</a>さんのところで<a href="http://www.appbank.net/2009/02/12/iphone-application/9101.php">ログ</a>があるので参照。<br />
みんな終始笑顔で、全世界で開発したアプリを使ってもらえるという喜びが伝わってくるよう。<br />
アップルに苦言を呈することもあるけど、年会費１万円という中での仕事ぶりには驚きが。<br />
shachiさんをはじめ様々な方が言われていた、機能を削ぎ落とすというのは重要だと再認識。iPhoneでのアプリ占有時間を増やすのではなく、起動回数を増やしたほうがいいアプリじゃないかなって私は思う。<br />
情報交換に関しては現在進行形でいい方向へ向かっているんじゃないかな？今年入ってから加速してるイメージ。</p>
<h5>【12-A-3】 時を超えたプログラミングの道への道</h5>
<p>角谷信太郎 氏</p>
<p>ソフトウェアでは、新たな社会構造を作る機会がある。<br />
開発だけがアジャイルではいけないよ！マネージメント、デプロイもアジャイルに！！</p>
<h5>【12-C-4】 クラウドプラットフォームの実際</h5>
<p>岡本充洋 氏</p>
<p>Salesforceの宣伝らしさがまったく見えないテンポのいいプレゼンがプロフェッショナル。<br />
シングルテナントのスケーラビリティ問題とマルチテナントのカスタマイズ問題を解決<br />
クラウドサービスというのは、クラウドを作るか、クラウドの上で何をするかの２つしかない。<br />
デモ見てるとブラウザ上でコードアシストもできたり、クラウドをクラウドで作ってるという現実が斬新。<br />
Eclipseでもプラグインあるし、気軽に試してみてねーって感じだったので試してみようかな</p>
<h5>【12-B-5】 ブラウザJavaScript高速化JITバトル最終決戦</h5>
<p>森田創 氏</p>
<p>Chrome(V8) vs Safari(SquirrelFish Extreme) vs Firefox(Trace Monkey)の高速化方法をアルゴリズムとか比較<br />
何で今までJavaScriptは遅かったの？→うざいダイアログやブラクラしか使い道がなかったから＞＜<br />
それに、言語仕様的に高速化しにくい<br />
高速化３つのキーワード ・クラスがない・メソッド呼び出し・正規表現<br />
コミットされてるソース見ると今後の流行りがわかるらしい。んで、GeoLocationみたいな実装があるらしい！これは見なくちゃ！！</p>
<h5>【12-B-6】 PHP/MySQL を用いた大規模向けパッケージソフトウェア開発</h5>
<p>田中裕一 氏</p>
<p>サイボウズガルーン。パッケージソフトの肝は、ユーザの操作性・機能も重要だけど、管理者が管理しやすいことを忘れちゃいけない。<br />
サイボウズではブラウザで４秒以内に表示されればokというルールを設定して、検証<br />
動作環境に合わせた最適な構成になるように実証して、設定を切り分け</p>
<h5>【12-C-7】 株式会社はてなの開発戦略</h5>
<p>舘野祐一 氏</p>
<p>館野さんってこんこんのsecondlifeさんだったんですね、わーい<br />
はてなの開発戦略と聞いて、勝手に外部的なものを想像してただけにgitの話とはビックリ！git厨恐るべし<br />
私は今までgitを「ジット」と読んでました「ギット」なんすね、恥ずかしいわ＞＜<br />
svnのブランチ作るのってそんなに面倒かな？GUI厨なんでCUIでコマンド打つ方がよっぽど面倒！<br />
ただ、gitもtortoiseGitがあるので、将来はsubversionとも変わらなくなって来るらしい<br />
後半は、はてブのリニューアルについて。前回のはてブはsqlで直DB読んでたりして密結合だったけど、JSONやRSSを使って疎結合にしたから機能追加とか制限なくできるよ！って話。squidでキャッシュさせてるから速度面でそんなに遅くなるようなこともないみたい。<br />
ポストイットとホワイトボードでのタスク管理は真似して取り入れたいな</p>
<h4>2009年2月13日（金）</h4>
<h5>【13-A-1】 これからのWebテクノロジーを予測する</h5>
<p>秋元裕樹 氏</p>
<p>これからという未知の予測というより既存の技術がどうなっていくかっていう内容だったと思う<br />
Web2.0<br />
クラウドコンピューティング：日本にはマッチしないよね<br />
OpenID：ログインウィンドウというUIの慣れをどう解決していくか、採用すると得する仕組みを作っていかないと<br />
OpenSocial：課金をどう解決？<br />
OAuth：twitterで実験中らしい。これ早くこないとパスワードの問題がどんどん表面化していくと思う、期待<br />
CGM/UGC：（答えは会場のみで）<br />
ブラウザ：標準化されていい世の中になったよね。ただ、携帯・TV・ゲーム機を考えちゃうとアレだけど<br />
RIA：去年のデブサミはRIAテーマのセッション多かったけど、まだ波がきてないよね、なんでだろ？<br />
Yahoo!に対するGoogleといい、次というのは必ず来る<br />
なんでも作ってみて、公開しようよ</p>
<h5>【13-B-2】 パネルディスカッション：クラウド時代のプログラミングスタイルを語り合おう</h5>
<p>米持幸寿 氏/ 萩原正義 氏/ 松尾貴史 氏/ 及川喜之 氏</p>
<p>Google AppEngine、Salesforce、Azure（、IBM社内クラウド）のパネルディスカッションでの戦いを期待してたけど<br />
それぞれの長所を発表してるだけに聞こえて、少し退屈<br />
5分というデモ時間を守らないのには見ている側からもイラっときた＞＜</p>
<p>（途中昼飯と美容院行ってたので3コマ抜けてます、決してサボっていたわけでは…）</p>
<h5>【13-A-6】 ひよこクラブ ver.Engineer</h5>
<p>庄司嘉織 氏/ 谷口公一 氏/ 堀邦明 氏/ 一井崇 氏</p>
<p>勉強の仕方やアウトプットを紹介しつつ、聴衆のみなさんも壇上に立とうよ！いい刺激になるライトニングトーク<br />
大学では「人に聞くな！まず調べろ！！」という教育されていたので、庄司さんの「ぐぐれかすっていわれないよ」というのにはハッとした。<br />
訊かないことでコミュニケーションを遮断してるようなモヤモヤが私の中にあるので、これからは積極的に「教えてクン」になろうかと。度が過ぎたらググれカスって言ってください。<br />
そして、知らないことをググって調べてるときに見つからないときには諦めるという谷口さんの考え方、今度からは自分がアウトプットした情報をググって見つけられるようにする。素敵です。</p>
<h5>【13-A-7】 Webセキュリティ攻守攻防パネルディスカッション「Webアプリケーション／Ajaxセキュリティ徹底バトル」</h5>
<p>竹迫良範 氏/ 徳丸浩 氏/ はせがわようすけ 氏/ はまちちゃん 氏/ 大垣靖男 氏</p>
<p>豪華すぎて鼻血が出る。それに糸柳さんたちもいたし、隣の隣の席の方とはまちちゃんがリアルタイムでtwitterしてるよ（藁）とかコミュニケーションとったり、会場全体が異様な雰囲気でしたねw</p>
<p>無知な私にとってIPAの果たしてる仕組み（報告者と対象の折衝役）ってのもわかりやすかったし、手法を実演してくれたりワクワクしながら楽しく参加させていただきました。<br />
幸いにも私ははまちちゃんのウィルスに感染しなかったようでピンピンして名古屋に帰れましたが、潜伏期間とかないよね。</p>
<p>今年も２日間があっという間に終わり。翔泳社さま、スポンサーさま、そしてエンジニアの皆さん、ありがとうございました。</p>
]]></content:encoded>
			<wfw:commentRss>http://creco.net/2009/02/16/devsumi2009/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://creco.net/2009/02/16/devsumi2009/" />
	</item>
		<item>
		<title>イーモバイルのサービスエリアをGoogle Earthに重ねてみる</title>
		<link>http://creco.net/2008/08/11/e-mobile_service_area_over_google-earth/</link>
		<comments>http://creco.net/2008/08/11/e-mobile_service_area_over_google-earth/#comments</comments>
		<pubDate>Sun, 10 Aug 2008 23:39:17 +0000</pubDate>
		<dc:creator>inagaki</dc:creator>
				<category><![CDATA[作ってみた]]></category>
		<category><![CDATA[Google Maps]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[イーモバイル]]></category>

		<guid isPermaLink="false">http://inagaki.co.uk/archives/134</guid>
		<description><![CDATA[&#160;&#160; 
携帯電話のサービスエリアって繋がるのが当然になってあまり気にしなくなっていたんだけど、イーモバイルはサービスエリアが都市部に限定されてるから、否が応でも気にしないと大変なことになる。
それで、 [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://creco.net/wp-content/uploads/20080811.jpg" rel="lightbox[438]"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="20080811" border="0" alt="20080811" src="http://creco.net/wp-content/uploads/20080811_thumb.jpg" width="420" height="270" /></a>&#160;&#160; </p>
<p>携帯電話のサービスエリアって繋がるのが当然になってあまり気にしなくなっていたんだけど、イーモバイルはサービスエリアが都市部に限定されてるから、否が応でも気にしないと大変なことになる。</p>
<p>それで、イーモバイルのサイトには<a href="http://emobile.jp/area/area.html">EM モバイルブロードバンドサービスエリア</a>としてサービス提供地域が確認できるようになってるんだけど、Googleマップみたいにドラッグでスクロールできるわけでもなく、いまいちな使い勝手。    <br />他にはPDFでもダウンロードできるようになってて、印刷するには丁度いいんだけど、サイト上で見られる提供地域よりも古い情報（２００８年５月）となってるし、解像度がいまいち。</p>
<p>上の画像はサイトのPNG画像とPDFを比較してみた図。</p>
<p>そこで、サイトのPNG画像を取得してGoogle Earthにオーバーレイできればよくない？いいんじゃね！</p>
<p>ということで作ってみる。</p>
<h3>イーモバイルの画像ファイルについての考察１</h3>
<p>まず、重ね合わせる元となるPNG画像を取ってこないといけないんだけど、ファイル名の命名規則を調べて、効率的に取ってこないと駄目だよね。</p>
<p>イーモバイルサイトで表示サービスエリアの移動操作はJavaScriptを使ってるので、そのソースを見て、なんとなく動作を理解する。</p>
<p>どうやら、緯度・経度がファイル名に対応しているらしい。第一段階はこんな具合。</p>
<p><a title="http://emobile.jp/area/area/map1/5236/5236.png" href="http://emobile.jp/area/area/map1/5236/5236.png" rel="lightbox[438]">http://emobile.jp/area/area/map1/5236/5236.png</a>    <br /><strong>map1</strong>：ズーム（横幅）。map1は横幅160km。    <br /><strong>5236</strong>：前の２桁が緯度の軸、後ろの２桁が経度の軸。んで、後から色々試してわかったんだけど、前の２桁は2/3でかけると緯度となり、後ろの２桁は100を足すと経度となる。    <br />加えて画像ファイルの表示範囲は上下左右位置の画像ファイルと半分重なるようになっている。</p>
<p>画像が提供されないエリアについては、下のソースみたくJavaScriptでフラグが管理されてあるのでそれを読み取ってエクセルにマッピングしてみた。</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:0cff2184-d481-4c0e-b3a1-062979a327b8" class="wlWriterSmartContent">
<pre class="js:collapse">    var inflag;
    inflag = 1;
    if (Mesh_1_XX &lt;= 21) {
        inflag = 1;
    }
    else if (Mesh_1_XX &lt;= 25) {
        if (Mesh_1_YY &gt;= 36 &amp;&amp; Mesh_1_YY &lt;= 38) {
            inflag = 0;
        };
    }
    else if (Mesh_1_XX &lt;= 27) {
        if (Mesh_1_YY &gt;= 36 &amp;&amp; Mesh_1_YY &lt;= 40) {
            inflag = 0;
（以下省略）</pre>
</div>
<p><a href="http://creco.net/wp-content/uploads/20080811_2.jpg" rel="lightbox[438]"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="20080811_2" border="0" alt="20080811_2" src="http://creco.net/wp-content/uploads/20080811_2_thumb.jpg" width="420" height="270" /></a></p>
<p>これで、第一段階のKMLはPHPで生成して完成。</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:37506416-c0d6-4d90-8053-46dfa76e897c" class="wlWriterSmartContent">
<pre class="php:collapse">&lt;?php

print '&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;'.&quot;n&quot;;
print '&lt;kml xmlns=&quot;http://earth.google.com/kml/2.2&quot;&gt;'.&quot;n&quot;;
print '&lt;Document&gt;'.&quot;n&quot;;
print '	&lt;name&gt;emobile&lt;/name&gt;'.&quot;n&quot;;

for($i=36;$i&lt;=68;$i++){
	for($j=22;$j&lt;=45;$j++){

		$inflag = 1;

		if ($j &lt;= 21) {
			$inflag = 1;
		}elseif ($j &lt;= 25) {
			if ($i &gt;= 36 &amp;&amp; $i &lt;= 38) {
				$inflag = 0;
			};
		}elseif ($j &lt;= 27) {
			if ($i &gt;= 36 &amp;&amp; $i &lt;= 40) {
				$inflag = 0;
			};
		}elseif ($j &lt;= 29) {
			if ($i &gt;= 39 &amp;&amp; $i &lt;= 52) {
				$inflag = 0;
			};
		}elseif ($j &lt;= 30) {
			if ($i &gt;= 42 &amp;&amp; $i &lt;= 52) {
				$inflag = 0;
			};
		}elseif ($j &lt;= 31) {
			if ($i &gt;= 45 &amp;&amp; $i &lt;= 52) {
				$inflag = 0;
			};
		}elseif ($j &lt;= 35) {
			if ($i &gt;= 49 &amp;&amp; $i &lt;= 54) {
				$inflag = 0;
			};
		}elseif ($j &lt;= 38) {
			if ($i &gt;= 49 &amp;&amp; $i &lt;= 57) {
				$inflag = 0;
			};
		}elseif ($j &lt;= 39) {
			if ($i &gt;= 49 &amp;&amp; $i &lt;= 64) {
				$inflag = 0;
			};
		}elseif ($j &lt;= 41) {
			if ($i &gt;= 52 &amp;&amp; $i &lt;= 68) {
				$inflag = 0;
			};
		}elseif ($j &lt;= 42) {
			if ($i &gt;= 58 &amp;&amp; $i &lt;= 68) {
				$inflag = 0;
			};
		}elseif ($j &lt;= 43) {
			if ($i &gt;= 62 &amp;&amp; $i &lt;= 67) {
				$inflag = 0;
			};
		}elseif ($j &lt;= 45) {
			if ($i &gt;= 64 &amp;&amp; $i &lt;= 66) {
				$inflag = 0;
			};
		};

		if($inflag){
			continue;
		}

		print '	&lt;GroundOverlay&gt;'.&quot;n&quot;;
		print '		&lt;name&gt;emobile&lt;/name&gt;'.&quot;n&quot;;
		print '		&lt;Icon&gt;'.&quot;n&quot;;
		print '			&lt;href&gt;http://emobile.jp/area/area/map1/'.$i.$j.'/'.$i.$j.'.png&lt;/href&gt;'.&quot;n&quot;;
		print '		&lt;/Icon&gt;'.&quot;n&quot;;
		print '		&lt;LatLonBox&gt;'.&quot;n&quot;;
		print '			&lt;north&gt;'.(($i+2)/3*2).'&lt;/north&gt;'.&quot;n&quot;;
		print '			&lt;south&gt;'.($i/3*2).'&lt;/south&gt;'.&quot;n&quot;;
		print '			&lt;east&gt;'.($j+2+100).'&lt;/east&gt;'.&quot;n&quot;;
		print '			&lt;west&gt;'.($j+100).'&lt;/west&gt;'.&quot;n&quot;;
		print '		&lt;/LatLonBox&gt;'.&quot;n&quot;;
		print '	&lt;/GroundOverlay&gt;'.&quot;n&quot;;
	}
}

print '&lt;/Document&gt;'.&quot;n&quot;;
print '&lt;/kml&gt;'.&quot;n&quot;;

?&gt;</pre>
</div>
<h3>イーモバイルの画像ファイルについての考察２</h3>
<p>第一段階では解像度になっとくできないので、第二段階（横幅40km）を取ってくることにする。</p>
<p><a title="http://emobile.jp/area/area/map2/5236/52364D.png" href="http://emobile.jp/area/area/map2/5236/52364D.png" rel="lightbox[438]">http://emobile.jp/area/area/map2/5236/52364D.png</a></p>
<p><strong>52364D</strong>：前の４桁については第一段階と同じ、後ろの２文字は第一段階のエリアを１６分割した場所を示す。</p>
<p>上を北にした地図表現だと次のような場所。</p>
<table border="1" cellspacing="0" cellpadding="2" width="400">
<tbody>
<tr>
<td valign="top" width="100">3C</td>
<td valign="top" width="100">3D</td>
<td valign="top" width="99">4C</td>
<td valign="top" width="99">4D</td>
</tr>
<tr>
<td valign="top" width="100">3A</td>
<td valign="top" width="100">3B</td>
<td valign="top" width="99">4A</td>
<td valign="top" width="99">4B</td>
</tr>
<tr>
<td valign="top" width="100">1C</td>
<td valign="top" width="100">1D</td>
<td valign="top" width="99">2C</td>
<td valign="top" width="99">2D</td>
</tr>
<tr>
<td valign="top" width="100">1A</td>
<td valign="top" width="100">1B</td>
<td valign="top" width="99">2A</td>
<td valign="top" width="100">2B</td>
</tr>
</tbody>
</table>
<p>これさえわかれば、あとは同じなので、KMLにしてGoogle Earthで表示してみる。</p>
<p>死亡。</p>
<p>オーバーレイの画像をインターネットから取得して読み込んでいき、沖縄から九州まで時間をかけながら徐々に埋まっていくんだけど、福岡が見えないうちに動作が重たくなって、しまいにはGoogle Earthが落ちた。</p>
<p>よく考えれば、4000枚ものPNG画像をダウンロードしながら表示させるなんて無理ありすぎです。ごめんなさい。</p>
<h3>それならば画像を合成してやればok</h3>
<p>何度も画像をダウンロードしてるようだとイーモバイルに怒られるので、一旦ローカルに保存してから、それをPHPで１６枚を１枚の画像に合成。</p>
<p>あとは第一段階のKMLを修正（重ね合わせの範囲が違うので）して、ようやくやりたいことができた！</p>
<p><a href="http://creco.net/wp-content/uploads/20080811_3.jpg" rel="lightbox[438]"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="20080811_3" border="0" alt="20080811_3" src="http://creco.net/wp-content/uploads/20080811_3_thumb.jpg" width="420" height="270" /></a></p>
<p>発展としては、サービス提供エリアを画像認識でトレース→ベクトルデータに変換→SWFに。</p>
<p>イーモバイルだけじゃなく他の３キャリアのサービス提供エリアも同じことをする（調べたところ、全キャリアで画像によるサービスエリア表示をしていたので可能）。</p>
<p>全キャリアの重ね合わせをトグルできるようにして、キャリアごとにサービスエリアを比較できるようになっちゃう！！！</p>
<p>需要あるのかわかんないけど、勉強がてら近いうちにやってみたい。</p>
]]></content:encoded>
			<wfw:commentRss>http://creco.net/2008/08/11/e-mobile_service_area_over_google-earth/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://creco.net/2008/08/11/e-mobile_service_area_over_google-earth/" />
	</item>
		<item>
		<title>Pythonおもしろくなってきたかも</title>
		<link>http://creco.net/2008/07/30/interested_in_python/</link>
		<comments>http://creco.net/2008/07/30/interested_in_python/#comments</comments>
		<pubDate>Tue, 29 Jul 2008 18:16:32 +0000</pubDate>
		<dc:creator>inagaki</dc:creator>
				<category><![CDATA[作ってみた]]></category>
		<category><![CDATA[GPS]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://inagaki.co.uk/archives/122</guid>
		<description><![CDATA[ 
ぶっちゃけていうと、素のままではできることが少なく、最初からいろんな関数があたえられてるPHPと比べると大変なんだけど、シンプルさとソースの見やすさから好きになりそうな言語。わかりやすいし。
それで、GPSとのシリア [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://creco.net/wp-content/uploads/20080730.jpg" rel="lightbox[429]"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="20080730" border="0" alt="20080730" src="http://creco.net/wp-content/uploads/20080730_thumb.jpg" width="324" height="244" /></a> </p>
<p>ぶっちゃけていうと、素のままではできることが少なく、最初からいろんな関数があたえられてるPHPと比べると大変なんだけど、シンプルさとソースの見やすさから好きになりそうな言語。わかりやすいし。</p>
<p>それで、GPSとのシリアル通信のプログラムなんだけど、   <br />今まで readline() で読んでたところを、timeout値を1秒近辺（後述）にし read() で取ってやるとつまりもなく、非常にスムース</p>
<p>GPSからの出力データは1秒おきにどばっとくる。そこで、timeout値は0.9秒にしてやって、データがシンクロできるようにとPythonの計算時間を考慮して、一定のコンマ秒で read() する時間を逐次調節するように</p>
<p>ソースは以下の通り</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:63a42e4b-559e-4b0a-aaac-32c07989f89a" class="wlWriterSmartContent">
<pre class="py:collapse">#!/usr/bin/python

import sys, os, os.path, serial, urllib, urllib2, socket, thread, time

socket.setdefaulttimeout(10)

serialPort = 'COM6' #EeePC usb
#serialPort = 'COM3' #EeePC bluetooth
url = 'hogehoge'

tryCount = 0
baseTime = 0

def getGprmcSentence():
	global baseTime

	while True:
		try :
			buffer = ser.read(1000)
		except :
			print &quot;error&quot;
			return &quot;error&quot;

		if int(time.time()) + baseTime - time.time() &gt; 0:
			time.sleep(int(time.time()) + baseTime - time.time() )

		if buffer[0:6] != '$GPGGA':
			print 'sync...'+&quot;\n&quot;
			time.sleep(0.1)
			if baseTime &gt; 0.9:
				baseTime -= 0.9
			else:
				baseTime += 0.1

		if buffer[12:13] == '0':
			lines = buffer.split(&quot;\r\n&quot;)
			data = []

			for line in lines:
				nmea = line.split(',')

				if nmea[0] == '$GPGGA':
					if len(nmea) == 15 and nmea[14][0:1] == '*':
						data.append(nmea[9])
				elif nmea[0] == '$GPRMC':
					if len(nmea) == 13 and nmea[12][1:2] == '*':
						data.append(nmea[3])
						data.append(nmea[5])
						data.append(nmea[7])
						data.append(nmea[8])
						data.append(nmea[9])
						data.append(nmea[1])

			args = (data,)
			print &quot;thread start...&quot;
			thread.start_new_thread(putGpsData, args)

def putGpsData(args) :

	global tryCount

	params = {
	    &quot;date&quot; : args[5],
	    &quot;time&quot; : args[6],
	    &quot;latitude&quot; : args[1],
	    &quot;longitude&quot; : args[2],
	    &quot;altitude&quot; : args[0],
	    &quot;speed&quot; : args[3],
	    &quot;heading&quot; : args[4],
	}

	try:
		urllib2.urlopen(url, urllib.urlencode(params))
	except urllib2.HTTPError, e:
		print e

	tryCount = tryCount+1

	print tryCount
	print args
	print &quot;\n&quot;

def connect() :
	global ser, baseTime

	try:
		ser = serial.Serial(serialPort, 38400, bytesize=8, parity='N', stopbits=1, timeout=0.9, xonxoff=0, rtscts=0)
	except serial.SerialException, e:
		print e

	baseTime = time.time() - int(time.time());

	while True:
		temp = getGprmcSentence()
		if temp == &quot;error&quot;:
			ser.close()
			return

	ser.close()

while True:
	connect()
	time.sleep(5)
	print &quot;reconnect...&quot;</pre>
</div>
<p>んで、あとはGPSのデータから読み取ったデータにおいて10秒おきにスレッドでPUTしてやる。</p>
<p>そのPUTもhttpのタイムアウト値が10秒以上超してしまうと、整合性があわなくなるので、httpのタイムアウト値も10秒に設定</p>
<p>以前は、NMEAフォーマットのRMCセンテンスだけしかとってなかったので高度が取得できなかったけど、GGAセンテンスも読み取って高度をゲットや！</p>
<p>最後に、USBやBluetoothが途中に抜かれたり、通信エラーしても復帰できるように例外処理からsleep()かけて5秒後に復帰処理するように</p>
<p>PHPのほうは、Ajaxによる更新時間とGPSデータの更新時間が近すぎるとタイミングによってデータの2重取得や取得逃しが発生するので、GPSデータの更新時間から5秒後に更新する（実際にはサーバ時間で秒数の一桁が5秒のとき・・・サーバ時間が正しいことが前提だけどね）ように初回Ajax更新時間を調節</p>
<p>いろんなところにいって早く試したいなｗ</p>
]]></content:encoded>
			<wfw:commentRss>http://creco.net/2008/07/30/interested_in_python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://creco.net/2008/07/30/interested_in_python/" />
	</item>
	</channel>
</rss>
