The smallest difference between 2 Angles

放肆的年华 提交于 2019-11-26 21:21:23

This gives a signed angle for any angles:

a = targetA - sourceA
a = (a + 180) % 360 - 180

Beware in many languages the modulo operation returns a value with the same sign as the dividend (like C, C++, C#, JavaScript, full list here). This requires a custom mod function like so:

mod = (a, n) -> a - floor(a/n) * n

Or so:

mod = (a, n) -> (a % n + n) % n

If angles are within [-180, 180] this also works:

a = targetA - sourceA
a += (a>180) ? -360 : (a<-180) ? 360 : 0

In a more verbose way:

a = targetA - sourceA
a -= 360 if a > 180
a += 360 if a < -180

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.

If your two angles are x and y, then one of the angles between them is abs(x - y). The other angle is (2 * PI) - abs(x - y). So the value of the smallest of the 2 angles is:

min((2 * PI) - abs(x - y), abs(x - y))

This gives you the absolute value of the angle, and it assumes the inputs are normalized (ie: within the range [0, 2π)).

If you want to preserve the sign (ie: direction) of the angle and also accept angles outside the range [0, 2π) you can generalize the above. Here's Python code for the generalized version:

PI = math.pi
TAU = 2*PI
def smallestSignedAngleBetween(x, y):
    a = (x - y) % TAU
    b = (y - x) % TAU
    return -a if a < b else b

Note that the % operator does not behave the same in all languages, particularly when negative values are involved, so if porting some sign adjustments may be necessary.

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)

For UnityEngine users, the easy way is just to use Mathf.DeltaAngle.

Arithmetical (as opposed to algorithmic) solution:

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

There is no need to compute trigonometric functions. The simple code in C language is:

#include <math.h>
#define PIV2 M_PI+M_PI
#define C360 360.0000000000000000000
double difangrad(double x, double y)
{
double arg;

arg = fmod(y-x, PIV2);
if (arg < 0 )  arg  = arg + PIV2;
if (arg > M_PI) arg  = arg - PIV2;

return (-arg);
}
double difangdeg(double x, double y)
{
double arg;
arg = fmod(y-x, C360);
if (arg < 0 )  arg  = arg + C360;
if (arg > 180) arg  = arg - C360;
return (-arg);
}

let dif = a - b , in radians

dif = difangrad(a,b);

let dif = a - b , in degrees

dif = difangdeg(a,b);

difangdeg(180.000000 , -180.000000) = 0.000000
difangdeg(-180.000000 , 180.000000) = -0.000000
difangdeg(359.000000 , 1.000000) = -2.000000
difangdeg(1.000000 , 359.000000) = 2.000000

No sin, no cos, no tan,.... only geometry!!!!

An efficient code in C++ is:

inline double getAbsoluteDiff2Angles(const double x, const double y, const double c)
{
    // c can be PI or 180;
    return c - fabs(fmod(fabs(x - y), 2*c) - c);
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!