Расчет угла между линией, определяемой двумя точками - PullRequest
35 голосов
/ 20 апреля 2010

В настоящее время я разрабатываю простую 2D-игру для Android. У меня есть стационарный объект, который расположен в центре экрана, и я пытаюсь заставить этот объект вращаться и указывать на область на экране, к которой пользователь прикасается. У меня есть постоянные координаты, которые представляют центр экрана, и я могу получить координаты точки, на которую нажимает пользователь. Я использую формулу, изложенную на этом форуме: Как получить угол между двумя точками?

  • В нем говорится следующее: «Если вы хотите угол между линией, определяемой этими двумя точками, и горизонтальной осью:

    double angle = atan2(y2 - y1, x2 - x1) * 180 / PI;".
    
  • Я реализовал это, но я думаю, что тот факт, что я работаю в экранных координатах, вызывает неправильный расчет, поскольку координата Y обращена. Я не уверен, если это правильный путь, любые другие мысли или предложения приветствуются.

Ответы [ 4 ]

58 голосов
/ 20 апреля 2010

Допущения: x - горизонтальная ось, которая увеличивается при движении слева направо. y - вертикальная ось, которая увеличивается снизу вверх. (touch_x, touch_y) это выбранная пользователем точка. (center_x, center_y) - это точка в центре экран. theta измеряется против часовой стрелки от оси +x. Тогда:

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

Редактировать : вы упомянули в комментарии, что y увеличивается сверху вниз. В этом кейс

delta_y = center_y - touch_y

Но было бы правильнее описать это как выражение (touch_x, touch_y) в полярных координатах относительно (center_x, center_y). Как отметил ChrisF, идея определения «угла между двумя точками» не совсем ясна.

29 голосов
/ 18 октября 2011

У меня была потребность в подобной функциональности, поэтому после долгих потягиваний волос я придумал функцию ниже

/**
 * 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);
}
16 голосов
/ 15 декабря 2014

Несколько ответов здесь пытались объяснить проблему «экрана», где top left - это 0,0, а bottom right - (положительно) screen width, screen height. Большинство сеток имеют положительную ось Y выше X, а не ниже.

Следующий метод будет работать со значениями экрана вместо значений «сетки». Единственное отличие от исключенного ответа - значения Y инвертированы.

<code>/**
 * 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
 * 
* @param p1 * @param p2 * @return - двойной от 0 до 360 * / public static double angleOf (PointF p1, PointF p2) { // ПРИМЕЧАНИЕ. Помните, что у большинства математик ось Y положительна над X. // Тем не менее, для экранов у нас есть Y как положительный ниже. По этой причине, // значения Y инвертируются для получения ожидаемых результатов. окончательный двойной deltaY = (p1.y - p2.y); окончательный двойной deltaX = (p2.x - p1.x); окончательный двойной результат = Math.toDegrees (Math.atan2 (deltaY, deltaX)); возврат (результат
1 голос
/ 21 апреля 2013

"начало координат находится в верхнем левом углу экрана, и координата Y увеличивается с понижением, в то время как координата X увеличивается вправо, как обычно. Я предполагаю, что возникает вопрос: нужно ли преобразовывать координаты экрана? в декартовых координатах перед применением вышеуказанной формулы? "

Если бы вы вычисляли угол, используя декартовы координаты, и обе точки были в квадранте 1 (где x> 0 и y> 0), ситуация была бы идентична координатам пикселя экрана (за исключением перевернутого Y Если вы отрицаете Y, чтобы получить его правой стороной вверх, это становится квадрантом 4 ...). Преобразование координат пикселов экрана в декартово не меняет угол.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...