Алгоритм или формула для кратчайшего направления движения между двумя градусами по кругу? - PullRequest
6 голосов
/ 15 сентября 2011

Дано два градуса на круге 360 градусов. Давайте назовем их Источник и Назначение.

Например, источник может быть 120 градусов, а пункт назначения - 30 градусов.

Существует ли элегантное решение вопроса о том, какое направление движения от источника к пункту назначения короче, т. Е. Короче по часовой стрелке (при увеличении градусов) или против часовой стрелки (при уменьшении градусов)?

Например, с указанными выше градусами, решение будет таким: Идти против часовой стрелки. С другой стороны, если для источника выбрано значение 350, а для пункта назначения - 20, решение будет следующим: по часовой стрелке.

Ответы [ 5 ]

12 голосов
/ 15 сентября 2011
if ((dest - source + 360) % 360 < 180)
  // clockwise
else
  // anti-clockwise

Кстати, ваше соглашение о том, что по часовой стрелке == "увеличение градусов" является противоположностью соглашению по тригонометрии 101 , которое использует остальной мир, и поэтому сбивает с толку ( во всяком случае, для меня).

3 голосов
/ 15 сентября 2011

Рассчитайте разницу, затем нормализуйте ее до +/- 180.Положительные числа указывают на перемещение в направлении увеличения угла (в вашем случае по часовой стрелке).

1 голос
/ 14 декабря 2017

Это функция, которую я использую для вывода кратчайшего расстояния между двумя градусами с отрицательными и положительными числами. Он также работает на выходе за пределы диапазона 0–360.

function shortestDistDegrees(start, stop) {      
  const modDiff = (stop - start) % 360;
  let shortestDistance = 180 - Math.abs(Math.abs(modDiff) - 180);
  return (modDiff + 360) % 360 < 180 ? shortestDistance *= 1 : shortestDistance *= -1;
}

shortestDistDegrees(50, -20)   // Output: -70
shortestDistDegrees(-30, -370) // Output: 20
shortestDistDegrees(160, -710) // Output: -150
1 голос
/ 03 ноября 2016

Этот алгоритм я использую для своих игровых камер:

rotSpeed = 0.25;                      //arbitrary speed of rotation

angleDiff      = 180-abs(abs(source-dest)-180);            //find difference and wrap
angleDiffPlus  = 180-abs(abs((source+rotSpeed)-dest)-180); //calculate effect of adding
angleDiffMinus = 180-abs(abs((source-rotSpeed)-dest)-180); //           ... subtracting

if(angleDiffPlus < angleDiff){        //if adding to ∠source reduces difference
    source += rotSpeed;               //add to ∠source
}else if(angleDiffMinus < angleDiff){ //if SUBTRACTING from ∠source reduces difference
    source -= rotSpeed;               //subtract from ∠source
}else{                                //if difference smaller than rotation speed
    source = dest;                    //set ∠source to ∠destination
}

«Заворачивая» угол, мы можем рассчитать разницу. Затем мы можем проверить текущую разницу по сравнению с прогнозами, чтобы увидеть, какое направление фактически уменьшит разницу.

0 голосов
/ 15 сентября 2011

Общий ответ здесь: «Арифметика по модулю».Вы можете прочитать об этом, оно того стоит.

...