Comment déterminer si V3 est entre V1 et V2 quand on passe de V1 à V2 sens inverse des aiguilles?

StackOverflow https://stackoverflow.com/questions/693806

  •  22-08-2019
  •  | 
  •  

Question

J'ai trois vecteurs V1, V2 et V3. Leurs points d'origine sont sur l'origine des axes. Comment pourrais-je savoir si V3 est entre V1 et V2 lorsque je me déplace dans le sens antihoraire de V1 à V2?

texte alt http://www.freeimagehosting.net/uploads/1448ea8896.jpg

Il ne peut pas être fait avec l'obtention de leurs angles et d'évaluer ce genre de conditions (pseudo-code):

if angle(V3) > angle(V1) && angle(V3) < angle(V2) 
   printf("V3 is between V1 and V2") 
else 
   printf("out of the interval")

Pour voir son défaut, supposons que la fonction angle donne des angles dans la plage de [-pi pi]. Donc, si l'angle (V1) = 120 (en degrés), l'angle (V2) = -130 et angle (V3) = 150 alors la réponse (selon le code ci-dessus) est "hors de l'intervalle", bien que si vous vous déplacez sens inverse des aiguilles de V1 à V2, il est entre eux.

Vous pouvez suggérer d'ajouter 2 * pi à l'angle (V2) ou quelque chose comme ça, mais je l'ai essayé des choses et ça ne fonctionne pas.

Je suis la programmation en Matlab.

EDIT 1:. Il est en 2D

Était-ce utile?

La solution

Puisque vous faites cela dans Matlab, voici une solution qui devrait fonctionner:

crossProds = [V1(1)*V2(2)-V1(2)*V2(1) ...
              V1(1)*V3(2)-V1(2)*V3(1) ...
              V3(1)*V2(2)-V3(2)*V2(1)];
if (all(crossProds >= 0) || ...
    (crossProds(1) < 0) && ~all(crossProds(2:3) < 0)),
  disp("V3 is between V1 and V2");
else
  disp("out of the interval");
end

EXPLICATION:

Le produit vectoriel entre les vecteurs 2-D V1 et V2 est stocké dans le premier élément de crossProds . Cette valeur sera supérieure ou égale à zéro si l'angle anti-horaire entre V1 et V2 est compris entre 0 et 180 degrés, inclus. Dans ce cas, lorsque V3 est compris entre V1 et V2 dans le sens inverse des aiguilles d'une montre, puis les produits croisés (V1, V3) et (V3, V2) sont également supérieure ou égale à zéro. Ceci explique la première vérification logique:

all(crossProds >= 0)

Si l'angle anti-horaire entre V1 et V2 est supérieur à 180 degrés, puis le produit vectoriel de ces deux vecteurs sera inférieur à zéro. Dans ce cas, lorsque V3 est entre V1 et V2 dans le sens dans le sens horaire puis les produits croisés (V1, V3) et (V3, V2) sont également inférieur à zéro. Par conséquent, si ces produits croisés sont pas à la fois inférieur à zéro puis V3 doit être entre V1 et V2 dans la dans le sens antihoraire direction. Ceci explique les deux contrôles logiques:

(crossProds(1) < 0) && ~all(crossProds(2:3) < 0)

Les contrôles ci-dessus logiques doivent couvrir toutes les situations possibles. Les opérateurs || et && sont courts Matlab: ils seront sauter les deuxièmes déclarations si elles ne sont pas nécessaires. Par exemple, si la première déclaration dans un OU est vrai, il n'y a aucune raison de vérifier la deuxième déclaration puisque seul un argument dans un ou doit être vrai pour que le résultat soit vrai.

Autres conseils

Calculer l'angle (V1), l'angle (V2) et l'angle (v3) (a1, a2, a3).

Modifier a2 et a3 (2 * pi ajouter si nécessaire) de telle sorte que

a1 <= a2 < a1 + 2*pi
a1 <= a3 < a1 + 2*pi

Maintenant, il vous suffit de comparer a2 et a3. V3 est comprise entre V1 et V2 se traduit a3 est inférieure à a2.

V1 est un faux problème. Vous allez juste vous confondre penser à trois angles à la fois.

  1. Faites tourner tout dans le sens horaire par l'angle (V1)
  2. Normaliser les deux angles restants [0360)

Maintenant, la question est simplement de comparer norme (angle (V2) -angle (V1)) et la norme (angle (V3) -angle (V1)).

méthode un peu plus facile pour la plupart des autres langages de programmation.

Si V1, V2 et V3 sont des vecteurs donnés, et nous devons décider temps V3 est entre V1 et V2, et Ri = atan2 (Vi) (qui retourne un angle en radians de -pi à pi):

Clockwise :

R1 -= R3;
R2 -= R3;

if (R1 < 0) R1 += 2 * PI;
if (R2 <= 0) R2 += 2 * PI;

return (r1 < r2);

antihoraire , remplacez juste R1 et R2.

Pour tester cette condition, vous devez calculer l'enroulement de deux triangles:

  1. Le triangle formé par V1, V3 et l'origine. Ce triangle doit être dans le sens antihoraire.

  2. Le triangle formé par V3, l'origine et V2. Ce triangle doit être dans le sens antihoraire ainsi.

Pour tester l'enroulement d'un triangle, il suffit de vérifier le signe de la croix-produit 2D des sommets.

Le test ressemble à ceci (désolé - C-code):

int IsBetween (vector v1, vector v2, vector v3)
{
  float winding1 = (v1.x * v3.y - v1.y * v3.x);
  float winding2 = (v3.x * v2.y - v3.y * v2.x);

  // this test could be exactly the wrong way around. This depends
  // on how you define your coordinate system (e.g. is Y going up or down?)

  if ((winding1 <0) && (winding2 < 0))
  {
    printf ("V3 is between them\n");
  }
  else
  {
    printf ("it's not\n");
  }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top