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
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
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.
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.
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)
Solution arithmétique (par opposition à algorithmique):
angle = Pi - abs(abs(a1 - a2) - Pi);
Pour les utilisateurs D'UnityEngine, le moyen le plus simple est simplement d'utiliser Mathf.DeltaAngle .
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!!!!
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);
}