2009-10-17 12 views
8

J'ai besoin d'un algorithme pour déterminer si un angle est dans une certaine quantité de degrés d'un autre angle.Trouver si un angle est à l'intérieur de X degrés d'un autre

Ma première pensée était (a-x < b) && (a+x > b), mais il échoue quand il doit travailler avec des angles qui enveloppent de -179 à 180.

Dans le schéma ci-dessus, la région (vert) que la l'angle doit être entre les enveloppes entre les côtés négatif et positif. Comment puis-je déterminer si l'angle (la ligne rouge) tombe à l'intérieur de cette région?

+0

Essayez la version mise à jour. – cletus

Répondre

7

essayer cette formule:

360-(|a-b|)%360<x || (|a-b|)%360<x 

Ou, in PHP:

<?php 

$b = 10; 
$angle1 = -179; 
$angle2 = 180; 

$diff = $angle1 - $angle2; 
if(abs($diff % 360) <= $b || (360-abs($diff % 360))<=$b) { 
    echo "yes"; 
} else { 
    echo "no"; 
} 

?> 
+0

Cela semble fonctionner! Merci Ngu. –

3

Comme Marcel le souligne à juste titre, modulo sur les nombres négatifs est potentiellement problématique. Aussi, quelle est la différence entre 355 et 5 degrés? Il pourrait être élaboré à 350 degrés, mais 10 degrés est probablement ce que les gens attendent. Nous faisons les hypothèses suivantes:

  1. nous voulons que l'angle positif le plus petit entre deux autres angles donc 0 <= diff <= 180;
  2. Nous travaillons en degrés. Si radians, remplacez 360 par 2*PI;
  3. les angles peuvent être positifs ou négatifs peuvent être en dehors de la plage -360 < x < 360 où x est un angle d'entrée et
  4. l'angle d'entrée ou la direction de la différence est sans importance.

Entrées: angles a et b. L'algorithme est donc simplement:

  1. Normaliser a et b à 0 <= x < 360;
  2. Calculer l'angle le plus court entre les deux angles normaux.

Pour la première étape, pour convertir l'angle de la gamme désirée, il existe deux possibilités:

  • x >= 0: normal = x% 360
  • x < 0: normal = (-x/360 + 1) * 360 + x

Le second est conçu pour éliminer toute ambiguïté sur la différence d'interprétation des opérations de module négatif. Donc, pour donner un exemple travaillé pour x = -400:

-x/360 + 1 
= -(-400)/360 + 1 
= 400/360 + 1 
= 1 + 1 
= 2 

puis

normal = 2 * 360 + (-400) 
     = 320 

donc pour les entrées 10 et -400 les angles normaux sont 10 et 320.

Maintenant, on calcule la le plus petit angle entre eux. Comme un contrôle de santé mentale, la somme de ces deux angles doit être 360. Dans ce cas, les possibilités sont 50 et 310 (dessinez-le et vous verrez cela).Pour ceux-ci sur:

normal1 = min(normal(a), normal(b)) 
normal2 = max(normal(a), normal(b)) 
angle1 = normal2 - normal1 
angle2 = 360 + normal1 - normal2 

Donc, pour notre exemple:

normal1 = min(320, 10) = 10 
normal2 = max(320, 10) = 320 
angle1 = normal2 - normal1 = 320 - 10 = 310 
angle2 = 360 + normal1 - normal2 = 360 + 10 - 320 = 50 

Vous remarquerez normal1 + normal2 = 360 (et vous pouvez même prouver que ce sera le cas si vous le souhaitez).

Enfin:

diff = min(normal1, normal2) 

ou 50 dans notre cas.

+0

Avez-vous une faute de frappe entre angle1 et angle2? –

+1

Modulo sur un nombre potentiellement négatif (diff) peut être dangereux dans certaines langues. –

+1

Est-ce que cela dépend de l'angle 0 - 360, ou est-ce que je peux l'utiliser avec des angles compris entre -180 et 180? –

1

Vous pouvez également utiliser un produit scalaire:

cos(a)*cos(b) + sin(a)*sin(b) >= cos(x) 
1

Pour un rayon de 1, la distance entre les extrémités de la ligne sont 2sin ((ab/2).) Jetez donc les 2 puisque vous êtes seulement intéressé par une comparaison, et compa re péché (x/2) avec le péché ((a-b)/2). Les fonctions de trig prennent soin de tout l'emballage.

0

C++ mise en œuvre:

float diff = fabsf(angle1 - angle2); 
bool isInRange = fmodf(diff, 360.0f) <= ANGLE_RANGE || 
       360.0f - fmodf(diff, 360.0f) <= ANGLE_RANGE;