1
votes

I am trying to do hit test on a rotated image object drawn on the canvas in surface view. When image is not rotate we can directly use left, top , width and height as boundaries to check whether the point lies within image rectangle. But how to do it when the object is rotated to some angle?

I am using: canvas.rotate(angle, pivotX ,pivotY); to draw the rotated image.

I could not get the rotated left and top of the image object. I tried to take original left and top of the image and when i tap on the screen i rotate the touch point back with same angle using:

angledTouchX = (float) (eventX * Math.cos(-objectAngle) - eventY * Math.sin(-objectAngle));
angledTouchY  = (float) (eventY * Math.sin(-objectAngle) + eventX * Math.cos(-objectAngle));

It does not work because it rotates the point wrt (0,0), but i want it wrt center of the image object.

2

2 Answers

2
votes

Was working on similar problem. In my case, I want to do a hottest between touchpoint and rotated and scaled view. So I transform touch point co-ordinate system according to view's rotation and check if its inside non-rotated view boundary or not.

Step

  1. Get touch point in screen co-ordinate system which received from event.getRawX() and event.getRawY()

  2. Target view location in screen location which received from

     int location[] = new int[2];
     view.getLocationOnScreen(location);
     int viewX = location[0];
     int viewY = location[1];
    
  3. Create vector as if view origin is the space origin

    float[] vec = new float[2];
    vec[0] = event.getRawX() - viewX;
    vec[1] = event.getRawY() - viewY;
    
  4. Rotate the vector

    Matrix matrix = new Matrix();
    matrix.setRotate(-1 * view.getRotation());
    matrix.mapVectors(vec);
    
  5. Change rotated vector to screen space

    vec[0] = vec[0] + viewX;
    vec[1] = vec[1] + viewY;
    
  6. Check if rotated touch co-ordinate is in view unrotated boundary

    if(( vec[0] > viewX 
        && vec[0] < (viewX + (view.getWidth() * view.getScaleX()) )) 
        &&( vec[1] > viewY 
        && vec[1] < (viewY + (view.getHeight() * view.getScaleY()) ))){
            isPointInTextView = true;
    } else {
            isPointInTextView = false;
    }
    
1
votes

You need to work with it mathematically. the best way to do is before you rotating the canvas change the position by width/2, height/2. Then apply rotation, finally move back to the previous location by width/2, height/2. Then your picture will be always rotated from the center. But still after rotating your new image will have a new size which fits as a rectagle align to screen sides.