Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Standard way to normalize an angle to +/- π radians in Java

Tags:

java

radians

Is there a library function or a well-known quick efficient way in Java to normalize an angle to +/- π — e.g. when adding two angles?

What I've got now (based on this answer) is basically the code below...

private static final double TWO_PI = 2 * Math.PI;

double normalize(double theta) {
    double normalized = theta % TWO_PI;
    normalized = (normalized + TWO_PI) % TWO_PI;
    return normalized <= Math.PI ? normalized : normalized - TWO_PI;
}

...but it seems a little complicated and performance-wise I'm not excited about the modulo operator. (Note that I can't guarantee theta isn't some relatively large number, so I don't think there's a pure addition/subtraction solution without looping. I don't actually know how a hand-rolled loop is likely to compare to %.)

Is there a well-tested optimized library function I can use, or a better algorithm, or is this as good as it gets?

like image 374
David Moles Avatar asked Jun 15 '14 22:06

David Moles


People also ask

What is angle normalization?

A normalized angle maps the full range of angles (360 degrees) to the range zero to one. The following table shows the relationship between normalized angles and degrees: Normalized. Degrees. 0.

How do you calculate radians in Java?

As a reminder, radians are just another way to express the measure of an angle, and the conversion is: double inRadians = inDegrees * PI / 180; inDegrees = inRadians * 180 / PI; Java makes this easy with toRadians and toDegrees: double inRadians = Math.

How do you convert degrees to radians?

How do we convert degrees to radians? To convert the value of the angle in degree, to its equivalent radians, we need to multiply the given value with π/180. For example, the value of 180 degrees is π in radians.


2 Answers

Apache commons has one:

http://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/org/apache/commons/math3/util/MathUtils.html#normalizeAngle(double, double)

normalize an angle between -π and +π

a = MathUtils.normalizeAngle(a, 0.0);

And looking at the source code, you could reproduce it with this (they use their own FastMath.floor but in case you want to do it without an external library):

theta - TWO_PI * Math.floor((theta + Math.PI) / TWO_PI)

Source is here: https://github.com/apache/commons-math/blob/53ec46ba272e23c0c96ada42f26f4e70e96f3115/src/main/java/org/apache/commons/math4/util/MathUtils.java#L107


Note for readers from the future: this method has just (June 2017) been removed from the latest commons-math 4.x codebase. If you're using a version after this, you'll want to use commons-numbers instead (once it's released) - currently:

a = PlaneAngleRadians.normalizeBetweenMinusPiAndPi(a);

or

a = PlaneAngleRadians.normalize(a, 0.0);
like image 161
CupawnTae Avatar answered Sep 24 '22 08:09

CupawnTae


There is only one 100% foolproof way:

public static double normalizeAngle(double angle) {
    return Math.atan2(Math.sin(angle), Math.cos(angle));
}   

Everything else is people trying to be too smart and failing.

like image 22
cohadar Avatar answered Sep 21 '22 08:09

cohadar