web-dev-qa-db-fra.com

La plus petite différence entre 2 angles

Soit 2 angles dans l'intervalle -PI -> PI autour d'une coordonnée, quelle est la valeur du plus petit des 2 angles entre eux?

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

Exemple:

Imaginez un cercle, avec 2 lignes sortant du centre, il y a 2 angles entre ces lignes, l’angle qu’ils forment à l’intérieur, aka le plus petit angle, et l’angle qu’ils forment à l’extérieur, aka le plus grand angle. Les deux angles ajoutés forment un cercle complet. Étant donné que chaque angle peut tenir dans une certaine plage, quelle est la valeur des plus petits angles, compte tenu du basculement

121
Tom J Nowell

Cela donne un angle signé pour tous les angles:

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

Attention, dans de nombreux langages, 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 personnalisée mod comme ceci:

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

Ou alors:

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

Si les angles sont compris entre [-180 et 180], cela fonctionne également:

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

De manière plus verbeuse:

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

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

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

Il retourne l'angle delta signé. Notez qu'en fonction de votre API l'ordre des paramètres de la fonction atan2 () peut être différent.

134
Peter B

Si vos deux angles sont x et y, l’un des angles qui les sépare 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 suppose que les entrées sont normalisées (c'est-à-dire: dans la plage [0, 2π)).

Si vous souhaitez conserver le signe (c.-à-d. La direction) de l'angle et également accepter des angles en dehors de la plage [0, 2π), Vous pouvez généraliser ce qui précède. Voici le code Python pour la 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 manière dans toutes les langues, en particulier lorsque des valeurs négatives sont impliquées. Par conséquent, le portage de certains ajustements de signe peut être nécessaire.

34
Laurence Gonsalves

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)
8
David Jones

Pour les utilisateurs de UnityEngine, le moyen le plus simple consiste simplement à utiliser Mathf.DeltaAngle .

6
Josh

Solution arithmétique (par opposition à algorithmique):

angle = Pi - abs(abs(a1 - a2) - Pi);
5
Rudolf Meijering

Un code efficace en C++ est:

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);
}
1
Adriel Jr

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

laisser 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 de la géométrie !!!!

1
Uli Gue