Marc Perry Marc Perry - 1 month ago 20
Android Question

Math complication when moving a rotated image

I have two images on screen and a listener that allows each of them to be moved individually. Additionally, one of them can rotate.

When a different setting is selected, the user can move both images at the same time. This listener works great when the images are moved individually, but as soon as the user chooses to move both of them at the same time, the rotated image will move along the tilted axes instead of the direction the user is moving their finger.

For example, if the image is rotated 90 degrees and the user moves their finger up, the image will go to the right. I have tried experimenting with trig, but this doesn't explain why it works correctly when just the rotated image is selected.

onTouch():

case MotionEvent.ACTION_DOWN: {
mPrevX = event.getX();
mPrevY = event.getY();

// Save the ID of this pointer.
mActivePointerId = event.getPointerId(0);
break;
}

case MotionEvent.ACTION_MOVE: {
// Find the index of the active pointer and fetch its position.
int pointerIndex = event.findPointerIndex(mActivePointerId);
if (pointerIndex != -1) {
float currX = event.getX(pointerIndex);
float currY = event.getY(pointerIndex);

// Only move if the ScaleGestureDetector isn't processing a
// gesture.
if (!mScaleGestureDetector.isInProgress()) {
if(!expandSelection){
adjustTranslation(view, currX - mPrevX, currY - mPrevY);
} else {
for(int i = 0; i < viewArr.length; i++){
adjustTranslation(viewArr[i], currX - mPrevX, currY - mPrevY);
}
}
}
}
}

break;
}


adjustTranslation():

private static void adjustTranslation(View view, float deltaX, float deltaY) {
float[] deltaVector = {deltaX, deltaY};
view.getMatrix().mapVectors(deltaVector);

view.setTranslationX( (view.getTranslationX() + deltaVector[0]) );
view.setTranslationY( (view.getTranslationY() + deltaVector[1]) );
}

Answer

I still need to make some adjustments for the scale factors, but below is the code I have so far that might save you some headaches if you come across something similar. It was the signs in the equations that really threw me off at first.

float cos = (float) Math.cos( Math.toRadians(viewArr[i].getRotation() ));
float sin = (float) Math.sin( Math.toRadians(viewArr[i].getRotation() ));

adjustTranslation(viewArr[i], (currX - mPrevX) * cos + (currY - mPrevY) * sin, (currY - mPrevY) * cos - (currX - mPrevX) * sin);

Edit: Here is the code that accounts for scale (assuming the image isn't skewed):

adjustTranslation(viewArr[i],
              ((currX - mPrevX) * cos + (currY - mPrevY) * sin) / viewArr[i].getScaleX(),
              ((currY - mPrevY) * cos - (currX - mPrevX) * sin) / viewArr[i].getScaleX());
Comments