tutorial studio java android graphics

java - studio - Cálculo del ángulo entre la línea definida por dos puntos.



canvas android (4)

Actualmente estoy desarrollando un juego 2D simple para Android. Tengo un objeto estacionario que está situado en el centro de la pantalla y estoy tratando de hacer que ese objeto gire y señale el área de la pantalla que toca el usuario. Tengo las coordenadas constantes que representan el centro de la pantalla y puedo obtener las coordenadas del punto en el que el usuario toca. Estoy usando la fórmula descrita en este foro: ¿Cómo obtener el ángulo entre dos puntos?

  • Dice lo siguiente: "Si desea el ángulo entre la línea definida por estos dos puntos y el eje horizontal:

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

  • Implementé esto, pero creo que el hecho de que esté trabajando en las coordenadas de la pantalla está causando un error de cálculo, ya que la coordenada Y está invertida. No estoy seguro de si esta es la forma correcta de hacerlo, cualquier otra idea o sugerencia es apreciada.


"el origen se encuentra en la parte superior izquierda de la pantalla y la coordenada Y aumenta al disminuir, mientras que la coordenada X aumenta a la derecha como normal. Supongo que mi pregunta es, ¿tengo que convertir las coordenadas de la pantalla en coordenadas cartesianas? Antes de aplicar la fórmula anterior? "

Si estuviera calculando el ángulo usando coordenadas cartesianas, y ambos puntos estuvieran en el cuadrante 1 (donde x> 0 e y> 0), la situación sería idéntica a las coordenadas de píxeles de la pantalla (excepto por la cosa al revés-Y). niega la Y para obtener el lado derecho hacia arriba, se convierte en el cuadrante 4 ...). Convertir las coordenadas de píxeles de la pantalla a cartesiano realmente no cambia el ángulo.


Algunas respuestas aquí han tratado de explicar el problema de "pantalla" donde la top left es 0,0 y la bottom right es el screen width, screen height (positivo) screen width, screen height . La mayoría de las cuadrículas tienen el eje Y como positivo por encima de X no por debajo.

El siguiente método funcionará con valores de pantalla en lugar de valores de "cuadrícula". La única diferencia con la respuesta exceptuada es que los valores de Y se invierten.

/** * Work out the angle from the x horizontal winding anti-clockwise * in screen space. * * The value returned from the following should be 315. * <pre> * x,y ------------- * | 1,1 * | / * | / * | 2,2 * </pre> * @param p1 * @param p2 * @return - a double from 0 to 360 */ public static double angleOf(PointF p1, PointF p2) { // NOTE: Remember that most math has the Y axis as positive above the X. // However, for screens we have Y as positive below. For this reason, // the Y values are inverted to get the expected results. final double deltaY = (p1.y - p2.y); final double deltaX = (p2.x - p1.x); final double result = Math.toDegrees(Math.atan2(deltaY, deltaX)); return (result < 0) ? (360d + result) : result; }


Supuestos: x es el eje horizontal, y aumenta cuando se mueve de izquierda a derecha. y es el eje vertical, y aumenta de abajo hacia arriba. (touch_x, touch_y) es el punto seleccionado por el usuario. (center_x, center_y) es el punto en el centro de la pantalla. theta se mide en sentido antihorario desde el eje +x . Entonces:

delta_x = touch_x - center_x delta_y = touch_y - center_y theta_radians = atan2(delta_y, delta_x)

Edición : mencionaste en un comentario que y aumenta de arriba a abajo. En ese caso,

delta_y = center_y - touch_y

Pero sería más correcto describir esto como expresando (touch_x, touch_y) en coordenadas polares relativas a (center_x, center_y) . Como mencionó ChrisF, la idea de tomar un "ángulo entre dos puntos" no está bien definida.


Yo también necesitaba una funcionalidad similar, así que, después de tirar mucho del cabello, se me ocurrió la siguiente función

/** * Fetches angle relative to screen centre point * where 3 O''Clock is 0 and 12 O''Clock is 270 degrees * * @param screenPoint * @return angle in degress from 0-360. */ public double getAngle(Point screenPoint) { double dx = screenPoint.getX() - mCentreX; // Minus to correct for coord re-mapping double dy = -(screenPoint.getY() - mCentreY); double inRads = Math.atan2(dy, dx); // We need to map to coord system when 0 degree is at 3 O''clock, 270 at 12 O''clock if (inRads < 0) inRads = Math.abs(inRads); else inRads = 2 * Math.PI - inRads; return Math.toDegrees(inRads); }