Is there an easy way to convert an angle (in degrees) to be between -179 and 180? I'm sure I could use mod (%) and some if statements, but it gets ugly:
//Make angle between 0 and 360
angle%=360;
//Make angle between -179 and 180
if (angle>180) angle-=360;
It just seems like there should be a simple math operation that will do both statements at the same time. I may just have to create a static method for the conversion for now.
The 180-degree angle is known as a straight angle. The sides of the angle are opposite to each other and they make a straight angle on a straight line through the vertex. The appearance of a 180-degree angle is a straight line.
Angles that are 180 degrees (θ = 180°) are known as straight angles. Angles between 180 and 360 degrees (180°< θ < 360°) are called reflex angles.
What is Wrap Angle? Wrap Angle is a measurement in degrees of the diameter of a sensor roller that the tensioned material contacts. Most tension sensing rollers have a minimum and maximum wrap angle they are compatible with.
// 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!)
This works with both negative and decimal numbers and doesn't require loops, nor trigonometric functions:
angle -= Math.floor(angle / 360 + 0.5) * 360
The result is in the [-180, 180) interval. For (-180, 180] interval, you can use this instead:
angle -= Math.ceil(angle / 360 - 0.5) * 360
I know that years have passed, but still.
This solution contains no loops, no subtracting, no modulo (allows to normalize to radians interval). Works for any input, including negative values, big values, edge cases.
double normalizedAngle = angle - (ceil((angle + M_PI)/(2*M_PI))-1)*2*M_PI; // (-Pi;Pi]:
double normalizedAngle = angle - (ceil((angle + 180)/360)-1)*360; // (-180;180]:
double normalizedAngle = angle - (floor((angle + M_PI)/(2*M_PI)))*2*M_PI; // [-Pi;Pi):
double normalizedAngle = angle - (floor((angle + 180)/360))*360; // [-180;180):
Not that smart, too, but no if.
angle = (angle + 179) % 360 - 179;
But I am not sure how Java handles modulo for negative numbers. This works only if -1 modulo 360 equals 359.
UPDATE
Just checked the docs and a % b
yields a value between -(|b| - 1)
and +(|b| - 1)
hence the code is broken. To account for negative values returned by the modulo operator one has to use the following.
angle = ((angle + 179) % 360 + 360) % 360 - 179;
But ... no ... never ... Use something similar to your initial solution, but fixed for values smaller then -179.
I'm a little late to the party, I know, but...
Most of these answers are no good, because they try to be clever and concise and then don't take care of edge cases.
It's a little more verbose, but if you want to make it work, just put in the logic to make it work. Don't try to be clever.
int normalizeAngle(int angle) { int newAngle = angle; while (newAngle <= -180) newAngle += 360; while (newAngle > 180) newAngle -= 360; return newAngle; }
This works and is reasonably clean and simple, without trying to be fancy. Note that only zero or one of the while loops can ever be run.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With