Search code examples
canvasbitmapautorotate

Rotate bitmap to movement direction


im trying to rotate a bitmap image acording to the movement direction on my motion event, lets say i have a image of a car from top view, i want the car to face in the direction of my movement, if im moving left it should turn 180 degress, and up it should turn to 90 and so on, pls excuss my bad english, iv only managed to rotate image acording to 0 being the center

    //this is how i rotate
double ComputeAngle(float x, float y){
    final double RADS_TO_DEGREES = 360  / (Math.PI * 2);
    double result = Math.atan2(y,x) * RADS_TO_DEGREES;

    if (result < 0){
        result = 360 + result;
    }
    return result;
}

//bitmap to rotate pretend its a car from top view
Bitmap bitmap;
//draws bitmap
private final RectF tmpRF = new RectF();
final void drawStrokePoint(Canvas c, float x, float y, float r) {
    tmpRF.set(x-r,y-r,x+r,y+r);

    //compute rotation
    float rotation = (float)ComputeAngle(x, y);

    Matrix matrix = new Matrix();
    matrix.postTranslate(-bitmap.getWidth()/2, -bitmap.getHeight()/2);
    matrix.postRotate(rotation);
    matrix.postTranslate(x, y);

    //draw bitmap
    c.drawBitmap(mAirbrushBits, matrix, null);
}

//get x y cords and draw at x y position
@Override
public boolean onTouchEvent(MotionEvent event)
{   
    float x = event.getX();
    float y = event.getY();

    switch (event.getAction() & MotionEvent.ACTION_MASK)
    {
        case MotionEvent.ACTION_DOWN:

            strokeX = x;
            strokeY = y;

            break;
        case MotionEvent.ACTION_POINTER_DOWN:

            break;
        case MotionEvent.ACTION_MOVE:

            drawStrokePoint(drawCanvas, x, y, currentWidth);

            break;
        case MotionEvent.ACTION_UP:

            break;
        case MotionEvent.ACTION_POINTER_UP:

            break;
    }

    return true;
}

Solution

  • In your method ComputeAngle you are't computing the right angle of movement. To do this you will need the old values of x and y as well. The method would look as follows:

    double ComputeAngle(double x, double y, double oldX, double oldY){
       // calculates the direction vector
       double directionX = x - oldX;
       double directionY = y - oldY;
    
       double vectorLength = Math.sqrt(directionX * directionX + directionY * directionY);
    
       // normalize the direction vector (coordinate / |v|)
       double normalizedX = directionX / vectorLength;
       double normalizedY = directionY / vectorLength;
    
       //Obtains the angle relative to the vector over the axis X (1,0)
       // The formula is the angle = scalar(v1, v2)/|v1||v2|
       double angleRadians = (normalizedX) / Math.sqrt(normalizedX*normalizedX + normalizedY*normalizedY);
    
       // This formula will give you a angle between 0 and 180, to obtain the other half you must check the direction
       if (directionY < 0)
          angleRadians += Math.PI;
    
       return angleRadians * RADS_TO_DEGREES;
    }