La plus petite différence entre 2 Angles

Étant donné 2 angles dans la plage-PI - > PI autour d'une coordonnée, Quelle est la valeur du plus petit des 2 angles entre eux?

En tenant compte du fait que la différence entre PI et-PI n'est pas 2 PI mais zéro.

Exemple:

Imaginez un cercle, avec 2 lignes provenant du centre, il y a 2 angles entre les lignes, l'angle qu'ils font à l'intérieur aka le plus petit angle, et l'angle qu'ils font à l'extérieur, aka le plus grand angle. Les deux les angles ajouté un cercle complet. Étant donné que chaque angle peut tenir dans une certaine plage, Quelle est la valeur des angles plus petits, en tenant compte du renversement

106
demandé sur Tom J Nowell 2009-12-10 09:01:33

8 réponses

Cela donne un angle signé pour tous les angles:

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

Attention dans de nombreuses langues, l'opération modulo renvoie une valeur avec le même signe que le dividende (comme C, C++, C#, JavaScript, liste complète ici). Cela nécessite une fonction mod personnalisée comme ceci:

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

Ou plus:

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

Si les angles sont dans [-180, 180] cela fonctionne aussi:

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

D'une manière plus verbeuse:

a = targetA - sourceA
a -= 360 if a > 180
a += 360 if a < -180
149
répondu bennedich 2014-10-25 10:51:48

X est l'angle cible. y est la source ou l'angle de départ:

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

Renvoie l'angle Delta signé. Notez que selon votre API, l'ordre des paramètres de la fonction atan2() peut être différent.

121
répondu Peter B 2010-01-05 17:16:33

Si vos deux angles sont x et y, alors l'un des angles entre eux est abs (x-y). L'autre angle est (2 * PI) - abs (x-y). Donc, la valeur du plus petit des 2 angles est:

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

Cela vous donne la valeur absolue de l'angle, et cela suppose que les entrées sont normalisées (c'est-à-dire: dans la plage [0, 2π)).

Si vous voulez conserver le signe (ie: direction) de l'angle et accepter également des angles en dehors de la plage [0, 2π) Vous pouvez généraliser ce qui précède. Voici le code Python pour le version généralisée:

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

Notez que l'opérateur % ne se comporte pas de la même façon dans toutes les langues, en particulier lorsque des valeurs négatives sont impliquées, donc si le portage des ajustements de signe peuvent être nécessaires.

31
répondu Laurence Gonsalves 2015-07-23 19:17:12

Je relève le défi de fournir la réponse signée:

def f(x,y):
  import math
  return min(y-x, y-x+2*math.pi, y-x-2*math.pi, key=abs)
7
répondu David Jones 2010-01-05 16:19:19

Solution arithmétique (par opposition à algorithmique):

angle = Pi - abs(abs(a1 - a2) - Pi);
4
répondu Rudolf Meijering 2012-03-28 12:07:02

Pour les utilisateurs D'UnityEngine, le moyen le plus simple est simplement d'utiliser Mathf.DeltaAngle .

4
répondu Josh 2016-02-07 20:03:30

Il n'est pas nécessaire de calculer des fonctions trigonométriques. Le code simple en langage C est:

#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);
}

Soit dif = A-b, en radians

dif = difangrad(a,b);

Soit dif = A-b, en degrés

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

Pas de péché, pas de cos, pas de bronzage,.... seulement la géométrie!!!!

1
répondu Uli Gue 2013-09-27 06:17:20

Un code efficace en c++ est:

double getAbsoluteDiff2Angles(const double x, const double y)
{
    return 180.0 - fabs(fmod(fabs(x - y), 360.0) - 180.0);
}
1
répondu Adriel Jr 2018-09-20 20:33:40