开发者

Algorithm or formula for the shortest direction of travel between two degrees on a circle?

Given two degrees on a 360 degree circle. Lets call them Source and Destination.

For example Source could be 120 degrees and Destination could be 30 degrees.

Is there an elegant solution to the question of which direction of travel from Source to Destination is shorter, i.e. is it shorter clockwise (increasing the degrees) or anti clockwise (decreasing the degrees)?

For example wi开发者_高级运维th the degrees given above then the solution would be: Go anti clockwise. On the other hand with Source as 350 and Destination as 20 then the solution would be: Go clockwise.


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

BTW, your convention that clockwise == "increasing the degrees" is the opposite of the Trigonometry 101 convention that the rest of the world is using, and is therefore confusing (was to me, anyhow).


Compute the difference, then normalise it to +/-180. Positive numbers indicate travel in the direction of increasing angle (clockwise in your case).


This is the function I use to output the shortest distance between two degrees with negative and positive numbers. It also works on degress outside the 0 - 360 ranges.

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


This is the algorithm I use for my in-game cameras:

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
}

By "wrapping" the angle we can calculate difference. We can then test the current difference versus predictions to see which direction would actually reduce the difference.


NPE's answer is good, but adding 360 before taking the modulo of 360 is a waste of time depending on the language. Therefore

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

Note that the Mod function has to return absolute values. For example
dest = 5, source = 10
wolfram alpha

-5 modulo 360 = 355

Beckhoff's implementation of Structured Text

LMOD(-5, 360) = -5
LMOD(-5+360, 360) = 355
MODABS(-5, 360) = 355


The general answer here is: "Modulo arithmetics". You might want to read up on that, it's worth it.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜