La plus petite différence entre 2 Angles
-
18-09-2019 - |
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
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)
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);
}