• スポンサードリンク

イメージの拡大縮小・移動・回転できるImageViewを作ってみた〜その4〜移動範囲の制限編

Android ImageView widget

とうとうこの時が来てしまいました(´・ω・`)イメージの移動制限の時間です(^^;)

兎にも角にもコードを載せます。最後のMatrix#postTranslateの辺りだけは以前載せたので見覚え有りますよね。

なんということでしょう、回転させさせなければ数行で終わってしまうはずの処理が、80行を超える巨大メソッドに成長してしまいました。実際にはこのメソッドから別のメソッドも呼び出しているのでゆうに100行超えです。

まず前提として、ImageViewの表示領域の上下左右を一定幅inset(各辺を内側に向けて一定幅ずつ小さく)したのがmLimitRect(移動可能範囲矩形)で、イメージの実際の大きさがmImageRectです(#initで設定しています)。また。mImageRectの四隅の点をMatrix#mapPointsを用いて拡大縮小・移動・回転させた座標がmTrans配列(x,yの座標ペア✕4頂点, イメージ矩形)になります。

この時、ImageView様内にイメージが見えている条件としては、

  1. mTransで定義される矩形の四隅の内少なくとも1つがmLimitRect内に存在する。
  2. mLimitRectで定義される矩形の四隅の内少なくとも1つがmTransで定義される四角内に存在する。
  3. mTransで定義される矩形の四辺の内少なくとも1辺がmLimitRectで定義される矩形の四辺の1つと交差している。

この3項目、合計24条件の内1つでも満たせばImageView内にイメージが見えていることになります。
なので、タッチ位置から移動距離を計算して、移動後の各座標を求め上記項目の内1つでも満たせばイメージを移動可能ということになります。ソースで言うと、18〜23行が項目1のチェック、24〜28行が項目2のチェック、32〜48行が項目3のチェックになります。53〜73行が移動可能範囲外にめり込まないように移動量を補正する部分、そして74〜84行のたった10行(実質4行)が実際の移動処理になります。

この処理の一番のポイントは11行目のMatrix#mapPointsですね。ImageView内で実際にイメージを表示する際と同等の座標変換を行ってImageViewのローカル座標として結果を得ることが出来ます。
実はMatrixにはRectFで定義される矩形に対して同様の座標変換を行うMatrix#mapRectというメソッドも有るのですが、得られる結果が四隅の座標では無く、元の頂点を座標変換した矩形に外接する各辺がx軸またはy軸と並行な矩形になってしまい、回転させた場合にかなりの確率で移動チェックをすり抜けてしまうので、今回は使えませんでした(でも回転させたイメージをはみ出すこと無く別のビットマップとして取得する時には便利ですよ)。

2つ目のポイントは、凸n角形(n>=3)内に点が含まれるかどうかを判定している#ptInPolyです。
コードはこんな感じ。

またまたベクトル登場です。ある頂点Aから時計回りの隣Bに向かう線分をベクトルとみなして、指定した点Pがそのベクトルの左右どちらに有るかを外積を使って判定しています。今回は引数を時計回りの凸n角形(n>=3)に限定しているので、指定した点が、全ての各頂点から時計回りに向かって右側または線分上(=外積が負または0)であれば、凸n角形内に指定した点が存在することになります。図を入れないとわかんないかなぁ?

本当はここまでの処理で、移動範囲のチェックが終わるつもりでした。でも見通しが甘かったですね。まだまだすり抜けてしまうのです。そこで登場したのが座標変換後のイメージ矩形と移動範囲矩形の辺の交差判定です。

またまた…またベクトル・・・線分の交差判定です。詳しくはWebで(笑)そのうち説明を載せるかもしれません。

とりあえず今回はここまで。お疲れ様でした。

あっ、ちなみに今回はひたすら計算に頼って判定していますが、他にもいくつか方法は有るので興味が有る方は調べてみてくださいね。

全体のソースはこちら(GitHub)

« »

  • スポンサードリンク

コメント