How can I find the difference between two angles?

Viewed 132535

Given 2 angles in the range -PI -> PI around a coordinate, what is the value of the smallest of the 2 angles between them?

Taking into account that the difference between PI and -PI is not 2 PI but zero.

Example:

Imagine a circle, with 2 lines coming out from the center, there are 2 angles between those lines, the angle they make on the inside aka the smaller angle, and the angle they make on the outside, aka the bigger angle. Both angles when added up make a full circle. Given that each angle can fit within a certain range, what is the smaller angles value, taking into account the rollover

10 Answers

x is the target angle. y is the source or starting angle:

atan2(sin(x-y), cos(x-y))

It returns the signed delta angle. Note that depending on your API the order of the parameters for the atan2() function might be different.

I rise to the challenge of providing the signed answer:

def f(x,y):
  import math
  return min(y-x, y-x+2*math.pi, y-x-2*math.pi, key=abs)

An efficient code in C++ that works for any angle and in both: radians and degrees is:

inline double getAbsoluteDiff2Angles(const double x, const double y, const double c)
{
    // c can be PI (for radians) or 180.0 (for degrees);
    return c - fabs(fmod(fabs(x - y), 2*c) - c);
}

See it working here: https://www.desmos.com/calculator/sbgxyfchjr

Arithmetical (as opposed to algorithmic) solution:

angle = Pi - abs(abs(a1 - a2) - Pi);

A simple method, which I use in C++ is:

double deltaOrientation = angle1 - angle2;
double delta =  remainder(deltaOrientation, 2*M_PI);

I absolutely love Peter B's answer above, but if you need a dead simple approach that produces the same results, here it is:

function absAngle(a) {
  // this yields correct counter-clock-wise numbers, like 350deg for -370
  return (360 + (a % 360)) % 360;
}

function angleDelta(a, b) {
  // https://gamedev.stackexchange.com/a/4472
  let delta = Math.abs(absAngle(a) - absAngle(b));
  let sign = absAngle(a) > absAngle(b) || delta >= 180 ? -1 : 1;
  return (180 - Math.abs(delta - 180)) * sign;
}

// sample output
for (let angle = -370; angle <= 370; angle+=20) {
  let testAngle = 10;
  console.log(testAngle, "->", angle, "=", angleDelta(testAngle, angle));
}

One thing to note is that I deliberately flipped the sign: counter-clockwise deltas are negative, and clockwise ones are positive

Related