Алгоритм или формула для кратчайшего направления движения между двумя градусами по окружности?

учитывая два градуса на круге 360 градусов. Назовем их источником и пунктом назначения.

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

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

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

5 ответов


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


if ((dest - source + 360) % 360 < 180)
  // clockwise
else
  // anti-clockwise

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


это функция, которую я использую для вывода кратчайшего расстояния между двумя градусами с отрицательными и положительными числами. Он также работает на degress вне рядов 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

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

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
}

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


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