Step3 可視判定とテキストの表示
1.ARテキストの読み込み
はじめにデータベースのARテキストの情報を読み込むために、CursorをARViewクラスに渡します。
GPSARAppのonCreateメソッド内のARViewの取得の内容を以下のように変更します。
// ARViewの取得 arView = new ARView(this, cursor); // 追記 cursor.close(); |
次に、ARViewのコンストラクタの内容を以下のように変更します。
public ARView(Context context, Cursor cursor) { super(context); // 追記:データベースの読み込みを行う readTable(cursor); } |
ARViewで実際にcursorを使用してデータを読み込むメソッドreadTableの内容は以下のようになります。
public class ARView extends View { // ARテキストの情報を保持するオブジェクト private ArrayList<GPSData> list; ・・・(中略)・・・ public void readTable(Cursor cursor) { // データベースに保存されている // 全てのARテキストの情報をlistに読み込む if (list != null) list.clear(); list = new ArrayList |
これでARテキストの読み込みが完了しました。それでは実際にARテキストを表示する処理を作成していきましょう。
2.ARテキストの描画
ARテキストの描画は、端末の現在地、カメラの向き、カメラの画角を考慮してARテキストが画面内にどのように写るかを計算します。ARテキストが一定以上遠い場所にあったりカメラの画角の範囲外であれば描画は行いません。
カメラの画角と範囲を定数として以下のように指定します。カメラの画角については厳密には端末毎に異なりますが、今回は携帯電話で一般に用いられる60度と指定します。また、画面のサイズについては端末ごとに大きく異なるのでコンストラクタで取得するようにします。
// カメラの画角を指定する private final int ANGLE = 60; // ARテキストの見える範囲を指定する // ここでは10kmほどに指定する private final float VIEW_LIMIT = 100000; // ディスプレイサイズ private int displayX; public ARView(Context context, Cursor cursor) { super(context); // データベースの読み込みを行う readTable(cursor); // 画面サイズの取得 Display disp = ((WindowManager) context .getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); displayX = disp.getWidth(); } |
それでは実際にARテキストの描画を行う処理を作成しましょう。OnDrawの内容を以下のように変更します。
@Override protected void onDraw(Canvas canvas) { Paint paint = new Paint(); paint.setAntiAlias(true); // 追記:ARテキストの描画 for (int i = 0; i < list.size(); i++) { // データの読み込み GPSData data = list.get(i); String info = data.info; int y = data.latitude; int x = data.longitude; // ARテキストとの距離を求める double dx = (x - posx); double dy = (y - posy); float distance = (float) Math.sqrt(Math.pow(dy, 2) + Math.pow(dx, 2)); // ARテキストとの距離が一定以上離れていたら、処理を行わずに次のARテキストの処理を行う if (distance > VIEW_LIMIT) { continue; } // ARテキストと現在地のなす角を求めて正規化する double angle = Math.atan2(dy, dx); float degree = (float) Math.toDegrees(angle); degree = -degree + 90; if (degree < 0) degree = 360 + degree; // 端末の向きとARテキストとの角度の差を求める float sub = degree - direction; if (sub < -180.0) sub += 360; if (sub > 180.0) sub -= 360; // ARテキストが視野に存在すれば描画処理を行う if (Math.abs(sub) < (ANGLE / 2)) { // 距離によってARテキストのサイズを決める float textSize = 50 * (float) (VIEW_LIMIT - distance) / VIEW_LIMIT; paint.setTextSize(textSize); // ARテキストの描画を描画する float textWidth = paint.measureText(info); float diff = (sub / (ANGLE / 2)) / 2; float left = (displayX / 2 + displayX * diff) - (textWidth / 2); drawBalloonText(canvas, paint, info, left, 55); } } // コンパスを描画する drawCompass(canvas, paint); } private void drawBalloonText(Canvas canvas, Paint paint, String text, float left, float top) { // 文字列の幅を取得 float textWidth = paint.measureText(text); // フォント情報の取得 FontMetrics fontMetrics = paint.getFontMetrics(); // 文字列の5ポイント外側を囲む座標を求める float bLeft = left - 5; float bRight = left + textWidth + 5; float bTop = top + fontMetrics.ascent - 5; float bBottom = top + fontMetrics.descent + 5; // 吹き出しの描画 RectF rectF = new RectF(bLeft, bTop, bRight, bBottom); paint.setColor(Color.LTGRAY); canvas.drawRoundRect(rectF, 5, 5, paint); // 三角形の描画 paint.setStyle(Paint.Style.FILL_AND_STROKE); Path path = new Path(); float center = left + textWidth / 2; float triangleSize = paint.getTextSize() / 3; path.moveTo(center, bBottom + triangleSize); path.lineTo(center - triangleSize / 2, bBottom - 1); path.lineTo(center + triangleSize / 2, bBottom - 1); path.lineTo(center, bBottom + triangleSize); canvas.drawPath(path, paint); // 文字列の描画 paint.setColor(Color.WHITE); canvas.drawText(text, left, top, paint); } |
メソッドdrawBalloonTextは表示内容をふき出しによって修飾します。実行すると下画像のようになることが確認出来ると思います。これでアプリの枠組みは完成しました。それでは最後に、新たにARテキストを登録する処理を作成しましょう。
第10回 ARゲームを作ってみよう(2)
Step1 カメラ画像へのオーバーレイと方位センサー情報の取得
Step2 位置情報の取得とデータベースの作成
Step3 可視判定とテキストの表示
Step4 現在位置の登録