Easy way to keeping angles between -179 and 180 degrees
// reduce the angle
angle = angle % 360;
// force it to be the positive remainder, so that 0 <= angle < 360
angle = (angle + 360) % 360;
// force into the minimum absolute value residue class, so that -180 < angle <= 180
if (angle > 180)
angle -= 360;
Try this instead!
atan2(sin(angle), cos(angle))
atan2
has a range of [-π, π). This takes advantage of the fact that tan θ = sin θ / cos θ, and that atan2
is smart enough to know which quadrant θ is in.
Since you want degrees, you will want to convert your angle to and from radians:
atan2(sin(angle * PI/180.0), cos(angle * PI/180.0)) * 180.0/PI
Update
My previous example was perfectly legitimate, but restricted the range to ±90°. atan2
's range is the desired value of -179° to 180°. Preserved below.
Try this:
asin(sin(angle)))
The domain of sin
is the real line, the range is [-1, 1]
. The domain of asin
is [-1, 1]
, and the range is [-PI/2, PI/2]
. Since asin
is the inverse of sin
, your input isn't changed (much, there's some drift because you're using floating point numbers). So you get your input value back, and you get the desired range as a side effect of the restricted range of the arcsine.
Since you want degrees, you will want to convert your angle to and from radians:
asin(sin(angle * PI/180.0)) * 180.0/PI
(Caveat: Trig functions are bazillions of times slower than simple divide and subtract operations, even if they are done in an FPU!)