Matrix.postRotate,画像を回転後のx,y座標.

1,711 views
Skip to first unread message

gami

unread,
Sep 12, 2013, 1:03:04 AM9/12/13
to android-g...@googlegroups.com
現在、canvasにbitmapを描画しているのですが、そのbitmapはドラッグなどで移動、拡大縮小、回転の機能が付加されています。
その画像はcanvasにいくつも描画できるのですがタッチした画像のみ移動、拡大縮小ができます。
現在の画像の描画範囲(タッチできる範囲)を取得できています。

しかし、Matrix.postRotateで中心点で回転させると最初はもちろんタッチ範囲を取得できているのですが、回転後は画像の左上のx,y座表は角度の分だけ傾きその画像の次のタッチ範囲は画像が描画されているところとは別になるわけです。

angle = (float) (previousLine.getAngle(line) * 180 / Math.PI);

imageMatrix.postRotate( angle , (float) (x + (imageWidth /2)),(float) (y + (imageHeight/2)));

previousLine = line;

当たり前といえばそうですが、回転後もタッチ範囲を画像の描画範囲に維持できる方法はありませんか?
アルゴリズムなどご教授おねがいします。

画像の形は正方形から長方形までまちまちです。

Masaki Natsuki

unread,
Sep 12, 2013, 9:19:33 PM9/12/13
to android-g...@googlegroups.com
Natsukiです

もっとうまい方法があるかもしれませんが、
stackoverflowで見かけた当たり判定のロジックです。
Bitmapとは別に 当たり判定用のPathと Regionを使います。


以下 四角形 x, y , width, height の場合

// Bitmapと同じ大きさのPathを作成
Path path = new Path();
path.moveTo(x, y);
path.lineTo(x + width, y);
path.lineTo(x + width, y + height);
path.lineTo(x, y + height);
path.close();

// Pathを変形
Matrix mat = new Matrix();
// ここで matrix で Bitmapと同じだけ変形
path.transform(mat);

// transform後の当たり判定作成
RectF rect = new RectF();
path.computeBounds(rect, true);
Region region = new Region();
region.setPath(path, new Region((int)rect.left, (int) rect.top, (int)
rect,right, (int)rect.bottom));

// 回転した当たり判定内部に座標が含まれるかどうか
boolean hit = region.contains( touchX, touchY ); // true = 含まれている









2013年9月12日 14:03 gami <sakaga...@gmail.com>:
> --
> このメールは Google グループのグループ「日本Androidの会」の登録者に送られています。
> このグループから退会し、メールの受信を停止するには、android-group-j...@googlegroups.com
> にメールを送信します。
> このグループに投稿するには、android-g...@googlegroups.com にメールを送信してください。
> http://groups.google.com/group/android-group-japan からこのグループにアクセスしてください。
> その他のオプションについては、https://groups.google.com/groups/opt_out にアクセスしてください。

gami

unread,
Sep 13, 2013, 12:11:34 AM9/13/13
to android-g...@googlegroups.com
    Natsukiさんpostありがとうございます。
上記方法ではなかなかうまくいきませんでした。pathを描画してみたところ画面端に描画されていたりしていました。

現在あたり判定に使っているのが下記のコードです。

//長方形や回転画像のタッチ判定
    public boolean isPointInsideRectangle(PointF pt, int imageWidth ,int imageHeight ,
    PointF center,float scale,float angle) {

    float mScale = scale;
    float mAngle = angle;
// 表示されている画像範囲の計算
float half_w = (imageWidth * mScale) / 2;
float half_h = (imageHeight * mScale) / 2;
float left   = center.x - half_w;
float right   = center.x + half_w;
float top   = center.y - half_h;
float bottom  = center.y + half_h;
RectF rect = new RectF(left, top, right, bottom);
// (1) 矩形の中心と点の距離を計算
double l = Math.sqrt(Math.pow(pt.x - center.x, 2) + Math.pow(pt.y - center.y, 2));
// (2)矩形の中心を原点として見た相対的な点C'の座標
PointF pt2 = new PointF();
pt2.x = pt.x - center.x;
pt2.y = pt.y - center.y;
// (3)点D'と横軸のなす角r2を求める
double r1, r2;
if(pt2.x != 0) {r1 = Math.atan(pt2.y / pt2.x);}
else{r1 = Math.PI / 2;}
r2 = r1 - mAngle;
// (4)点D'の座標
PointF pt3 = new PointF();
pt3.x = (float)(l * Math.cos(r2));
pt3.y = (float)(l * Math.sin(r2));
// (5)点Dに戻す
pt3.x += center.x;
pt3.y += center.y;
// 普通の矩形と点の当たり判定
if(rect.left <= pt3.x && pt3.x <= rect.right &&
rect.top <= pt3.y && pt3.y <= rect.bottom) {
return true;
}
return false;

Masaki Natsuki

unread,
Sep 13, 2013, 1:47:56 AM9/13/13
to android-g...@googlegroups.com
> // Pathを変形
> Matrix mat = new Matrix();
> // ここで matrix で Bitmapと同じだけ変形 <====== ここにコード追加
> path.transform(mat);


この部分を補足しておきます。

Bitmapの描画を

Matrix mat = new Matrix();
mat.preTranslate( -width * 0.5f, -height * 0.5f);
mat.postRotate( degree );
mat.postScale( scaleX , scaleY );
mat.postTranslate( x , y );
canvas.drawBitmap( bmp, mat, null);

と、このようにmatrixで変形させながら描画している前提として、
Path用意したPathも同じように変形させるのがミソです。





2013年9月13日 13:11 gami <sakaga...@gmail.com>:

gami

unread,
Sep 13, 2013, 5:33:31 AM9/13/13
to android-g...@googlegroups.com
Natsukiさん
なんどもすいません。せっかく教えて頂いたのに解決に至りませんでした。

なんとかして、回転後の画像描画位置の中心座標が取れれば解決できそうです。

Matrixでなにが問題かというとpostRotateした時のscaleの初期化などがいろいろと不便で仕方ないです。


On Thursday, September 12, 2013 2:03:04 PM UTC+9, gami wrote:

MORIHIRO

unread,
Sep 13, 2013, 5:57:06 AM9/13/13
to android-g...@googlegroups.com
Bitmapの描画に使ったMatrixを保持しているのであれば、
以下のような感じで判定するのが楽な気がします。
  Matrix invertMatrix = new Matrix();
  imageMatrix.invert(invertMatrix);
  float[] p = {pt.x, pt.y};
  invertMatrix.mapPoints(p);
  boolean hit = (0<p[0] && p[0]<imageWidth && 0<p[1] && p[1]<imageHeigth);


2013年9月12日木曜日 14時03分04秒 UTC+9 gami:

gami

unread,
Sep 13, 2013, 8:03:31 PM9/13/13
to android-g...@googlegroups.com

MORIHIROさん。

言わせてください・・・本当にありがとうございます。
思い通りの動きになりました。
Matrixに関してまだまだ知らないことがおおくて勉強不足を感じました。
ほんと、日々勉強です。
invert(Matrix)
mapPoints(p);
今回上記のものが勉強になりました。

細かいタッチのあたり判定は修正できそうです。

MORIHIRO様、長い事お付き合いしていただき感謝しています。

またこの場所にお世話になるかもしれませんがよろしくお願いします。

On Thursday, September 12, 2013 2:03:04 PM UTC+9, gami wrote:
Reply all
Reply to author
Forward
0 new messages