質問

Math has defeated me once again. This is such a simple task, but I can't manage to get it done.

Scenario: I draw on a SurfaceView a round image. The user touches a point on image border and starts to drag it adround. I need to rotate the circle image according to user movement. I have two important piece of information, the image center X,Y coordinates and the touched points coordinates.

enter image description here

As you can see in the image, the user touched a point, according to my draw the touched point angle should be around 40. I can't manage to calculate it properly.

I tried using this formula:

angle = Math.atan2(touchedY - centerY, touchedX - centerX) * 180 / Math.PI 

I can't manage to understand how I should calculate the angle, as it is now, it doesn't work properly and values are not good. For instance, in the case of the image, the angle calculate is -50.

Thank you for your time, any informations is gladly taken.

LE: Actually I did a mistake I think, as mentioned below. Should the circle be like:

enter image description here

役に立ちましたか?

解決

Let's reformulate the problem: You want to find the angle between two vectors. The first vector is the upvector going straigt up from your center-point (u), and the second vector is the vector from the center point to the touch point (v).

Now we can recall (or google) that

cos a = uv / (|u|*|v|)

Where a is the angle between the vectors and |u| is the length of a vector. The upvector, u, is (0, 1) and has length 1.

Multiplying the vectors by hand cancels the x-term and gives us something like this.

double tx = touch_x - center_x, ty = touch_y - center_y;
double t_length = Math.sqrt(tx*tx + ty*ty);
double a = Math.acos(ty / t_length);

Note how the v vector is obtained by subtracting the center point from the touch point. Remember to convert to degrees if needed.

他のヒント

first of all, the rotate angle should be determined by the origin of CenterX, and CenterY. So your (touchedY - centerY, touchedX - centerX) should be (centerY - touchedY, centerX - touchedX).

And the correct answer may be:

(int) (Math.toDegrees(Math.atan2(centerY - touchedY, centerX - touchedX)));

Hope it helps

You need 3 points for an angle. You only have 2 (center and touch). Choose a fixed 3rd point, for example the one at 90 in your picture, and use @vidstige's answer to find your equation.

I tried a lot of things to do something like that and come with this:

Its getting the view position instead of the center of the screen, but you can addapt it:

ROTATE IMAGE VIEW BASED ON TOUCH POINT:

     iv = (ImageView) findViewById(R.id.soldier); // img view to rotate
     int touch_x = (int) event.getX(); // touch point x
     int touch_y = (int) event.getY(); // touch point y
     int[] location = new int[2];
     iv.getLocationInWindow(location);   // get img location on screen

       float angle = (float) Math.toDegrees(Math.atan2( touch_x - location[0],    touch_y -   location[1]));

        if(angle < 0){
            angle += 360;
        }


     iv.setRotation(-angle);
private fun getAngle(touchX: Float, touchY: Float): Double {
    var angle: Double
    val x2 = touchX - centerX
    val y2 = touchY - centerY
    val d1 = Math.sqrt((centerY * centerY).toDouble())
    val d2 = Math.sqrt((x2 * x2 + y2 * y2).toDouble())
    if (touchX >= centerX) {
        angle = Math.toDegrees(Math.acos((-centerY * y2) / (d1 * d2)))
    } else
        angle = 360 - Math.toDegrees(Math.acos((-centerY * y2) / (d1 * d2)))
    return angle
}

where touchX = event.getX and touchY = event.getY

this for angle betweet two point in Degree

angle = (Math.atan2(y2-y1,x2-x1) *180 / Math.PI)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top