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.
精彩评论