2011-12-14
CakePHP2+PostgreSQLでGeoデータを簡単に扱う!?
PHP, PostgreSQL, CakePHP |
@tkengoさんから引き続き CakePHP Advent Calendar 14日目の記事です。
深く考えず参加申し込みをしたらダブルヘッダーになってしまいヒーヒー言っているわたなべです(^^;
この記事はCakePHP2系の記事です。
明日にはこんなイベントも開催されるようで、最近は位置情報を扱う機会も多いのではないかと思います。
先月くらいに位置情報に関して色々試していて、CakePHPから扱う場合にいつもと同じように扱いたいなぁということでPostgres Datasourceを拡張してみたので解説したいと思います。
PostgreSQLで扱える位置情報の種類
PostgreSQLで扱える位置情報関連のデータ型には以下のようなものがあります。
| 型名 | 表現 |
|---|---|
| point | 平面における座標点 |
| line | 無限の直線 |
| lseg | 有限の線分 |
| box | 矩形 |
| path | 閉経路 |
| path | 開経路 |
| polygon | 多角形 |
| circle | 円 |
今回は携帯での位置情報を簡単に扱えるようにという目標なのでこの中からデータ型としては 'point'型と'box'型のサポートをしました。
位置情報関連の演算子
下記のマニュアルページを見ていただければ分かる通り、たくさんの演算子がサポートされています。
今回はこの中から以下の演算子をサポートを追加しました。
| 演算子 | 説明 |
|---|---|
| @ | 含む、または境界上 |
| ~= | 同等か? |
| <-> | 距離 |
スキーマ定義
今回の追加機能のテスト用に作成したFixtureは下記になります。
<?php class PostgresGeoFixture extends CakeTestFixture { /** * name property * * @var string 'PostgresGeo' */ public $name = 'PostgresGeo'; /** * fields property * * @var array */ public $fields = array( 'id' => array('type' => 'integer', 'key' => 'primary'), 'loc' => array('type' => 'point', 'null' => false), 'rect' => array('type' => 'box', 'null' => false), ); }
point型の locとbox型の rect フィールドを作成しています。
使い方
データを保存する場合は、以下の様に座標データを配列形式で設定すればOKです。
box型の場合は左上の座標と、右下の座標を配列で渡します。
<?php $data = array( 'loc' => array(10.1,10.1), 'rect' => array(array(10.1,10.2), array(100.1,100.2)), ); $Model->create(); $Model->set($data); $result = $Model->save();
特定の円の中に含まれているデータを検索する場合はこんな感じです。
<?php // @ operator // compare to circle $conditions = array( 'loc @' => array('circle' => array('point'=> array(10.1,10.1), 100)), ); // order by distance $order = array( 'loc <-> point(10.1,10.1)' ); $result = $model->find('all', array('conditions'=>$conditions, 'order'=>$order));
この例では中心座標 10.1,10.1、半径100の範囲内に含まれるデータが取得できます。また、<->演算子で並べ替えることで、中心座標に近い順に並べ替えることが可能です。
Postgresデータソースのテストを書いてあるのでそちらも見ていただけると、もう少しイメージが湧くかと思います。
誤算
当初この修正を始めたときは、PostgreSQLデータソース内部ですべて解決できそうな気がした(^^; ので、CakePHP2をforkして作業を始めたのですが、実際に作業を進めて見た結果、DboSource(データベース関連データソースの共通クラス)にも手を入れないと実現ができませんでした。
さすがにDatasource固有の演算子サポートのためにDboSourceに手を入れる修正はコアに取り込んでもらえないなぁと思い、今後この機能をプラグイン化できないか調査をしているところです。
実際に動くコードは、GitHubに上がっているのでもし興味がある方は試してみてください。結構便利だと思いますよ。
明日は @scriptwork さんです。よろしくお願いします!
zinniaでお手軽手書き文字認識
iPhone |
@haoyayoi さんから引き続き iOS Advent Calendar 14日目の記事です。
アプリ自体はまだ2本しか出していないわたなべです。
iOS Advent Calendar はそうそうたるメンバーがとても参考になる記事を書かれているのでいろいろ勉強させてもらってます(><)!
こんな私ですが、@k_katsumiさんに背中を押されたので、最近試している手書き文字認識エンジン zinniaについて書いてみます
zinnia ってなに?
zinnia は Taku Kudoさんが作成された「手書き文字認識エンジン」です。このエンジンに文字のストローク座標の連続データを渡すことで、高速に文字を認識することができます。確からしさ順にN個の結果を取得することができるので、変換候補を表示したりも出来ます。
iPhone上で動かすには...
@FLCLjp さんが作成されたサンプルが Githubで公開されているのでそれを見るのが一番だと思います。
実際に動かしてみると以下のようにしっかり認識できるはずです。
で、これだけだと全く中身がない話になってしまうので(^^; もう少し書きますよ〜。
認識率は...
zinniaのサイト上で配布されれいる 認識用モデルファイル(Zinnia-Tomoe) を使って試用した感じではかなり認識率は高いと思います。ただ画数の少ない文字はどうしても正しく認識してくれないケースが多かったです。まぁ、仕方が無いですね。
ですが、特定の文字種に限って(たとえば数字だけとか...)認識できればいいのであれば、自前で認識用モデルファイルを作ってしまえばかなり認識率を高めることはできそうです。
実際、私を含め身近な数人に数字のストロークを入力してもらい作成した認識用モデルファイルを使うと、ほぼ100%に近い確率で認識できました!
認識用モデルファイル
認識用モデルファイルはS式で記述された学習データを元に、zinnia付属のコマンドで作成します。公式ページにも記述がありますが実際の形式は以下のような形式です。
S式フォーマット
(character (value 認識したい文字) (width キャンバス幅) (height キャンバス高さ) (strokes ((0画目x 0画目y) ... (0画目x 0画目y)) ((1画目x 0画目y) ... (1画目x 1画目y)) ((2画目x 2画目y) ... (2画目x 2画目y)) ...))
フォーマット自体はとてもシンプルなのですが、このデータを作るには実際に認識させるデバイス上で文字のストローク情報を集める必要があります。おそらくzinniaを使っている方はみんな何らかの文字収集ツールを書いてるんじゃないかなぁと思います。
ということで、自分用にiPhoneで動作するアプリを書いたので解説します。
手書きストローク収集ツール(TegakiStroke)
iPhone-Zinnia-TegakiStroke@GitHub
もともと自分用に収集アプリを書いていたのですが、不特定多数の人のストロークを集めたかったので、データをサーバーに上げる方式で作っていました。これだとお手軽に試してもらうわけにはいかないので、すべてのデータをローカルなsqlitedbに保存する形で作り直しました。テーブル構成は以下のようなとても簡単な作りになっているので、、付属のtemplate.dbを覗いてもらえればわかるかと思います。
モデル情報(models) => モデルに含まれる文字情報(characters) => 実際のストローク情報(strokes)
CREATE TABLE models (
id INTEGER PRIMARY KEY,
name TEXT,
created
);
CREATE TABLE characters (
id INTEGER PRIMARY KEY,
model_id INTEGER,
character TEXT,
created
);
CREATE TABLE strokes (
id INTEGER PRIMARY KEY,
character_id INTEGER,
strokes TEXT,
created
);
INSERT INTO models (name,created) values ('number', '2011/12/13');
INSERT INTO characters(model_id,character, created) values(1,'0','2011/12/13');
INSERT INTO characters(model_id,character, created) values(1,'1','2011/12/13');
... 以下略
実際の動作は...
まず入力するモデルを選んで...
「文字入力」ボタンを押して....
実際に文字を入力します....
登録されている文字の入力が終わると、文字一覧に戻ってくるので「S式書出し」ボタンを押せば完了です。
書きだしたデータは、Documentsフォルダに保存されていますのでiTunes ファイル共有か何かで取り出してください。
吐き出された、*.sファイルをzinnia付属の zinnia_learn にかければ実際に使えるモデルファイルが出来上がります。
またアプリ内部で使用している sqliteのファイルもDocumentsフォルダに保存してあるので、適宜モデルや文字を追加するなり、自前でstrokeデータを抜き出して加工するなり、いろいろできるのではないかと思います。
まとめ
zinniaを使うと非常に簡単に手書き文字認識を実装できます。実際のアプリで使うには色々と工夫が必要かと思いますが...。
ソースはGitHubに上げてありますので、試してみてください!
若干やっつけ感が漂っているところもありますが(^^; 、時間ができたら機能を追加していこうと思ってます。
明日は @hIDDEN_xv さんです!
2011-10-03
PHP Matsuriに参加しよう!
PHP, TitaniumMobile, CakePHP |
色々ばったばったしているわたなべです。
このエントリーは、10/15-16に大阪で開催されるPHP Matsuriのリレーブログエントリーです!
まだ若干の余裕はありますが、急がないと埋まってしまう可能性もあるので後悔したくない人は今すぐ申し込んでしまいましょう!
私は昨年のPHP Matsuriにも参加したのですが、私が感じたこうしたら楽しめた(はず)!という内容を書きたいと思います。
作るものをある程度考えておく
当日は興味深いセッションやワークショップが盛りだくさんなので、以外にハックの時間がとれないかもしれません。当日作るもの/やる事をある程度考えて事前準備をしておくと良いと思います。開発環境も準備出来る方は事前に準備しておくのも良いと思いますが、期間中に使用可能なインスタンスをスポンサーさんが貸してくれるとの話もある様なので、環境構築も周りのみんなの構築方法とかを聞きながら色々試すのも面白いと思います。
食事タイムにも交流
photo by @ichikaway
期間中は、参加者/ゲスト全員で食事をする機会が4回あります。この食事時間も絶好の交流のチャンスです。気になるゲストのそばに陣取るのもいいですね。また、気になる参加者やスタッフをポジションペーパーでチェックして一緒に食事をとるのも楽しいと思いますよ!
疲れたら休憩にして動き回る
photo by @ichikaway
講演/ワークショップ/ハックに疲れたら、少し休憩にしてうろうろしてみると面白いと思います。昨年は深夜にいきなりゲーム大会が始まったり、ビール片手に海外ゲストと談笑する人、喫煙スペースで延々開発談義をしている方とかもいました。
遅い時間になるとあちこちで「プシュ!」とビールの空く音が....!お酒が飲める人も飲めない人もあちこちで会話に花が咲いていると思います。興味のありそうな話が聞こえたらがんがん捕まえて交流する事をお勧めします。
英語は怖くない!?
英語は思っているほど怖くありません。中学生レベルの英語で十分コミュニケーションはとれます。別にとって食われる事はないので、海外ゲストにもガンガン話しかけてみましょう。世界が広がるはずです。
と、英語をしゃべれる人にいつも言われているので、私も今回はがんばろうと思います(^^;。
やった事を発表する
photo by @ichikaway
2日目の午後は参加者それぞれの成果をLT形式で発表する時間になります。「自分が作ったものなんてたいした事無いし...」とか「まだ未完成だから...」とか色々あって躊躇する人も多いとおもいますがそんな人は、@shin1x1さんの勉強会を楽しむなら発表しよう!を読んでみましょう!ここに書かれている、
「君の当たり前に僕らは感嘆させられるんだ」
は本当にその通りだと思います。発表する事で広がるものが絶対にあります!すてきな商品もある様なので、是非!
まとめ
という事でつらつらと書いてきましたが、PHP Matsuriは楽しいので是非参加してみんなでハックして交流しましょう!という事です。さあ、皆さん申し込みましょう!
明日は、上でも紹介した@shin1x1さんです、よろしくお願いしますー!
2011-08-17
candycaneをPostgreSQLにも対応させたい!
昨日の夜に社内用 redmine をアップデートしていたのですが、まだCakePHPもgitも覚えたての頃に、CakePHP開発合宿に参加して開発したのを思いだしたのか、急に candycane が気になったので、ちょっといじってみる事にしました。
まずは手始めに、手持ちのMacのPHP+MySQL環境にインストールしてみたのですが、まぁこれが超絶簡単。@yandoさんも書いていますが、本当に3分程度でインストールが完了してしまいました。
いよいよPostgreSQLに対応する作業ですが、実際にやった作業は以下のような感じ。
- MySQLの初期状態を元にCakePHPのschemaファイルを作成
- 上のschemaファイルを使ってPostgreSQL上にテーブルを作成
- MySQLのダンプファイルを元に初期データをインサート
- pg_dumpでダンプしたものを整形して初期化用sqlを作成
- インストーラのDB設定画面にDB選択フィールドを追加
- インストーラにPostgreSQLの接続確認処理 database.phpに選択されたdriverを書き込む処理を追加
- 選択されたドライバ毎に初期データ作成用sqlを切り替える処理を追加
とこんな感じです。途中、schema生成時にエラーが出てはまったのですがこれはcandycane開発当初にはまだリリースされていなかったPostgreSQL9.xに依存する問題だったので、CakePHP1.3.10CakePHP1.3.5で対応されたものを組み込んで対応しました。
インストール完了後に Administration -> informationをみるとこんな感じ。
ひとまず、無事PostgreSQLで動作させる事ができました。
実際にはいくつかの機能で正常に動作しない部分や、テストが通らない所があるので今後ちょっとづつ手を入れていこうと思ってます。
2011-04-11
電力使用量を表示するアプリを作りました
iPhone |
先週金曜日(4/8)、計画停電の「原則不実施」の発表日という絶妙のタイミング(^^; でしたが東京電力管内の電力使用量を表示する「電力グラフ」というアプリをリリースしました。
電力使用量を取得するAPIが続々リリースされ始めた3/24頃に、こんな事をつぶやいていたら@basukeにケツ叩かれたので作ってみました(^^;
グラフの描画は s7graphview を使わせてもらっています。また、通信関係の処理は three20 を使っています。
この2つのライブラリのおかげで比較的サクッと作れました。
主な機能はこんな感じです。
使用している情報は下記のAPIを使用しています。
- 電力使用量の情報は株式会社ユーザーローカルさんが提供している東京電力の電気使用状況 APIを使わせて頂いております。
- 関連情報はPFIさんが提供しているQuakeMemeの電力情報を利用させて頂いております。
計画停電のスケジュールは東京電力の発表しているデータを元に独自で作成したデータを使っています。この情報はAmazon S3上においてあったりします。
原則的に計画停電は実施されない事になった様ですが、これから夏にかけて電力が不足する事は変わらないと思うので、節電のお供に使って頂ければと思います。
*「電力グラフ」で使用している情報は、東京電力の発表に基づき情報を更新しておりますが、反映には時間差が生じます。 最新の情報は東京電力のサイト等でご確認ください。















