'Smallest difference between two angles?

I'm trying to calculate the smallest difference between two angles.

This is my current code (a slight variation of something I found online):

float a1 = MathHelper.ToDegrees(Rot);
float a2 = MathHelper.ToDegrees(m_fTargetRot);

float dif = (float)(Math.Abs(a1 - a2);

if (dif > 180)
  dif = 360 - dif;

dif = MathHelper.ToRadians(dif);

It works fine except for in cases at the edge of a circle. For example if the current angle is 355 and the target angle is 5 it calculates the difference is -350 rather than 10 since 365 degrees is equal to 5 degrees.

Any ideas on what I can do to make this work?



Solution 1:[1]

You would expand the check for out of bound angles:

if (dif < 0) dif = dif + 360;
if (dif > 180) dif = 360 - dif;

Solution 2:[2]

I never like handling the zero-wrapping with case statements. Instead, I use the definition of the dot product to compute the (unsigned) angle between two angles:

vec(a) . vec(b) = ||a|| ||b|| cos(theta)

We're just going to make a and b unit vectors, so ||a|| == ||b|| == 1.

Since vec(x) = [cos(x),sin(x)], we get:

unsigned_angle_theta(a,b) = acos(cos(a)cos(b) + sin(a)sin(b))

(n.b. all angles in radians)

Solution 3:[3]

You can normalize the result to be 0 <= theta < 360:

while(theta < 0) { theta += 360; }

If you want to keep the answer in radians (recommended):

const Double TwoPi = 2 * Math.Pi;
while(theta < 0) { theta += TwoPi; }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Guffa
Solution 2 Robert Calhoun
Solution 3 codekaizen