Question

Compte tenu de 2 angles dans la gamme -PI -> PI autour d'une coordonnée, quelle est la valeur de la plus petite des 2 angles entre eux

?

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

Exemple:

Imaginez un cercle, avec 2 lignes sortant du centre, il y a 2 angles entre les lignes, l'angle qu'ils font sur les alias intérieur plus petit angle , et l'angle qu'ils font sur la à l'extérieur, alias l'angle plus grand. Les deux angles lorsqu'on les additionne font un cercle complet. Étant donné que chaque angle peut entrer dans une certaine plage, ce qui est la plus petite valeur des angles, en tenant compte du retournement

Était-ce utile?

La solution

Cela donne un angle signé pour tous les angles:

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

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

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

Ou alors:

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 détaillée:

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

Autres conseils

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

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

Il retourne 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). Ainsi, la valeur de la plus petite des 2 angles est:

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

Cela vous donne la valeur absolue de l'angle, et il suppose que les entrées sont normalisées (ex: dans la plage [0, 2π)).

Si vous souhaitez conserver le signe (ie: direction) de l'angle et également accepter des angles hors 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 le même dans toutes les langues, en particulier lorsque les valeurs négatives sont impliqués, donc si le portage des ajustements des signes peut être nécessaire.

Je prends la parole pour 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)

Pour les utilisateurs UnityEngine, la voie facile est juste utiliser Mathf.DeltaAngle .

arithmétique (par opposition à algorithmique) solution:

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

Il n'y a pas besoin de calculer les fonctions trigonométriques. Le simple code 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);
}

let dif = a - b, en radians

dif = difangrad(a,b);

let 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 cos, tan pas, .... seulement la géométrie !!!!

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);
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top