2

Android用の「ナビゲーションタイプ」アプリを構築しています。

ナビゲーション部分については、ユーザーがタッチ イベントを使用してマップ (ビットマップ) を移動およびズームできるアクティビティを構築しています。また、マップはコンパスを使用して画面の中心を中心に回転します。

マトリックスを使用して画像を拡大縮小、転置、回転し、キャンバスに描画します。

以下は、画面の中央に画像を配置するために、ビューの読み込み時に呼び出されるコードです。

    image = new Matrix();
    image.setScale(zoom, zoom);

    image_center = new PointF(bmp.getWidth() / 2, bmp.getHeight() / 2);

    float centerScaledWidth = image_center.x * zoom;
    float centerScaledHeigth = image_center.y * zoom;

    image.postTranslate(
            screen_center.x -  centerScaledWidth, 
            screen_center.y - centerScaledHeigth);

画像の回転はpostRotateメソッドで行っています。

次に、onDraw()メソッドで呼び出すだけです

  canvas.drawBitmap(bmp, image, drawPaint);

問題は、ユーザーが画面に触れたときに、画像に触れたポイントを取得したいのですが、どうやら正しい位置を取得できないことです。画像マトリックスを反転して、タッチしたポイントを変換しようとしましたが、うまくいきません。

ポイント座標を変換する方法を誰かが知っていますか?

編集

このコードを翻訳に使用しています。 dxdyは、 onTouchリスナーから取得した変換値です。*new_center* は、この形式の float 値の配列です {x0, y0, x1, y1...}

  Matrix translated = new Matrix();
  Matrix inverted = new Matrix();

  translated.set(image);
  translated.postTranslate(dx, dy);

  translated.invert(inverted);
  inverted.mapPoints(new_center);
  translated.mapPoints(new_center);

  Log.i("new_center", new_center[0]+" "+new_center[1]);

実際に *new_center = {0,0}* として使用してみました:

変換された行列のみを適用すると、bmp の (0,0) ポイントと画面の (0,0) ポイントの間の距離は十分に計算されますが、回転は考慮されていないようです。

逆行列をポイントに適用すると、それらの結果が得られ、画像があらゆる方法で移動します

  12-26 13:26:08.481: I/new_center(11537): 1.9073486E-6 -1.4901161E-7
  12-26 13:26:08.581: I/new_center(11537): 0.0 -3.874302E-7
  12-26 13:26:08.631: I/new_center(11537): 1.9073486E-6 1.2516975E-6
  12-26 13:26:08.781: I/new_center(11537): -1.9073486E-6 -5.364418E-7
  12-26 13:26:08.951: I/new_center(11537): 0.0 2.682209E-7
  12-26 13:26:09.093: I/new_center(11537): 0.0 7.003546E-7

代わりに、画像上で変換された座標を調べていました。

私の考えは正しいですか?

4

1 に答える 1

3

わかったよ。

最初に、画像の移動とズームから回転を分離しました。

カスタム ImageView を作成したので、これは簡単でした。回転を ImageView のキャンバスに適用し、その他の変換を画像のマトリックスに適用します。

グローバルマトリックス変数を介してcanvaのマトリックスのトレースを取得します。

いくつかのコード:

対応するonTouchイベントの正しい動きを設定するには、まずキャンバスの逆行列を使用して、onTouchから渡されたポイント(開始点と停止点) を「元に戻す」

次に、x と y の差を計算し、それを画像行列に適用します。

  float[] movement = {start.x, start.y, stop.x, stop.y};

  Matrix c_t = new Matrix();
  canvas.invert(c_t);
  c_t.mapPoints(movement);

  float dx = movement[2] - movement[0];
  float dy = movement[3] - movement[1];

  image.postTranslate(dx, dy);

代わりに、 image.postTranslate(dx, dy);の前に、画像の動きがそのサイズを超えていないことを確認したい場合。あなたはこのコードを入れます:

  float[] new_center = {screen_center.x, screen_center.y};

  Matrix copy = new Matrix();
  copy.set(image);
  copy.postTranslate(dx, dy);

  Matrix translated = new Matrix();
  copy.invert(translated);
  translated.mapPoints(new_center);

  if ((new_center[0] > 0) && (new_center[0] < bmp.getWidth()) && 
    (new_center[1] > 0) && (new_center[1] < bmp.getHeight())) {

        // you can remove the image.postTranslate and copy the "copy" matrix instead
        image.set(copy);
  ...

次の点に注意してください。

A) 画像の中心回転は画面の中心なので、キャンバスの回転中に座標は変わりません

B) 画面の中心の座標を使用して、画像の回転中心を取得できます。

このメソッドを使用すると、すべてのタッチ イベントを画像座標に変換することもできます。

于 2012-12-26T17:41:30.930 に答える