コンパス使用の準備をする

 ここまでのプログラムを実行すると、画面の上半分にカメラ画像が、下半分に現在地の地図が表示されます。続いて、(1)実機(の背面のカメラ)が向いている方角の文字をカメラ画像に重ねて表示させる機能、(2)実機が向いている方角に合わせて地図の向きを回転させる機能、(3)実機の傾きに合わせて方角を表す文字を変形させる機能を追加して、ARアプリケーションとして仕上げていきましょう。

図9●TextBlockコントロールを配置してプロパティを設定する
図9●TextBlockコントロールを配置してプロパティを設定する
[画像のクリックで拡大表示]

 まず、実機が向いている方角に該当する文字をカメラ画像に重ねて表示させる処理を実装します。文字を表示させるため、ツールボックスからTextBlockコントロールを、デザイン画面の上半分にドラッグ&ドロップします。このTextBlockコントロールに、コンパスから取得した値に応じて「東」「西」「南」「北」の文字を表示させます。配置したコントロールをデザイン画面で適当な大きさに変更したら、プロパティウィンドウでFontFamily(フォントの種類)をYu Gothic、FontSize(フォントの大きさ)を100程度に設定してください(図9)。

 方角を測定するにはコンパスを使います。コンパスの機能を使う手順は、GPSを使うときと同じです。まず、ソリューションエクスプローラーの参照設定の上で右クリックして「参照の追加」を選択し、「Microsoft.Devices.Sensors」への参照を追加します。次に、ソースコードの既存のusing宣言文に、コンパスを使うためのusing宣言文を追加します(リスト10)。続いて、コンパスの値を取得するフィールドとして、compassの定義(リスト11)をGPSのwatcherフィールドの定義の直後に記述してください。

 さらに、コンパスを使うためのコード(リスト12)を、コンストラクター内のGPSを使うためのコード(リスト8)の直後に追加します。プログラムの3行目で+=まで入力すると図6のようなツールチップが表示されますので、Tabキーを2回押してcompass_CurrentValueChangedイベントハンドラを生成させます。

 リスト12ではコンパスの値を取得する間隔として、compass.TimeBetweenUpdateに値を設定しています(1)。式の右側のTimeSpanの第5引数はコンパスの値を取得する時間間隔を示す引数です(ミリ秒単位)。ここでは200を指定しましたので、コンパスの値を200ミリ秒(0.2秒)ごとに取得します。取得したコンパスの値が変わると、CurrentValueChangedイベントが発生し、compass_CurrentValueChangedイベントハンドラが呼び出される仕組みです。

センサー値の取得と表示を非同期で実行する

 compass_CurrentValueChangedイベントハンドラ(リスト13の(1))では、元からある例外発生のコードをコメントアウトして、画面を描画するUpdateUIメソッドを呼び出すコードを追加します。Updateメソッドは、コンパスから取得した値に基づいて文字を表示させるメソッドです(同(2))。

 compass_CurrentValueChangedイベントハンドラで、画面を描画するUpdateUIメソッドを直接呼び出すのではなく、Dispatcher.BeginInvokeを使って呼び出しているのに注意してください。Dispatcher.BeginInvokeを使うと、指定したメソッドを非同期で実行できます。

 Windows Phoneでは、パフォーマンスを向上させるために、コンパスや加速度計のようなセンサーを扱う処理と、画面描画を行う処理を、別々のスレッドで実行しています。そのため、コンパスで発生したイベントに対するイベントハンドラでは、画面描画に関する機能を直接呼び出すことができません。そのため、Dispatcher.BeginInvokeを使って非同期で実行しているわけです。

 UpdateUIメソッドのコードを見ていきましょう。コンパスの値を取得し、値によって表示させる文字を変えています。方角は0度から360度までの数値で取得しますので、0度以上45度未満と315度以上のときに「北」、45度以上135度未満のときに「東」といった具合です(リスト13の(2-1))。こうして選んだ文字をTextBlockのTextプロパティに代入します。

 さらに、画面上に文字を表示させる位置を、コンパスから取得した値によってずらしています。例えば、北北東を向いているときは「北」という文字を左寄りに、北北西を向いているときには右寄りに表示させます。これは、文字の表示に使用しているTextBlockのMarginプロパティを利用して実現しています。具体的には、文字の画面左端からの表示位置を計算した値をxフィールドに代入し、Marginプロパティに代入しています(リスト13の(2-2))。