Calcul efficace des angles dans le sens des aiguilles d'une montre entre des vecteurs
Traditionnellement, le calcul de l'angle entre deux vecteurs nécessitait l'utilisation du produit scalaire, qui détermine l'angle intérieur à l'intérieur la plage de 0 à 180 degrés. Cependant, cette approche présente des défis lors de la détermination du résultat approprié entre l'angle et son complémentaire.
Existe-t-il une méthode plus directe pour calculer l'angle dans le sens des aiguilles d'une montre ?
Cas 2D
De la même manière que le produit scalaire est lié au cosinus de l'angle, le déterminant est proportionnel à son sinus. En incorporant cette relation, nous pouvons calculer l'angle comme suit :
dot = x1 * x2 + y1 * y2 # Dot product between [x1, y1] and [x2, y2] det = x1 * y2 - y1 * x2 # Determinant angle = atan2(det, dot) # atan2(y, x) or atan2(sin, cos)
L'orientation de l'angle calculé s'aligne sur celle du système de coordonnées. Dans un système de coordonnées gaucher où x pointe vers la droite et y pointe vers le bas, les angles dans le sens des aiguilles d'une montre donneront des valeurs positives. À l’inverse, dans un système de coordonnées mathématiques où y pointe vers le haut, le résultat reflète les angles dans le sens inverse des aiguilles d’une montre, comme c’est l’habitude en mathématiques. L'échange de l'ordre des vecteurs d'entrée modifie le signe, offrant ainsi la possibilité de modifier le signe du résultat.
Cas 3D
En trois dimensions, les vecteurs arbitraires définissent leur propre axe de rotation perpendiculaire aux deux. Puisque cet axe n’a pas d’orientation fixe, il n’est pas possible de déterminer de manière unique la direction de l’angle de rotation. Une convention courante consiste à attribuer des angles positifs et à aligner l'axe pour s'adapter à cette convention. Dans ce contexte, le produit scalaire des vecteurs normalisés suffit pour le calcul de l'angle :
dot = x1 * x2 + y1 * y2 + z1 * z2 # Between [x1, y1, z1] and [x2, y2, z2] lenSq1 = x1 * x1 + y1 * y1 + z1 * z1 lenSq2 = x2 * x2 + y2 * y2 + z2 * z2 angle = acos(dot / sqrt(lenSq1 * lenSq2))
Plan intégré en 3D
Pour les vecteurs contraints dans un plan avec une normale connue vecteur n, il y a un cas particulier à considérer. L'axe de rotation coïncide avec n et l'orientation de n fixe l'orientation de l'axe. Dans ce scénario, nous pouvons modifier le calcul 2D ci-dessus pour inclure n dans le déterminant, le transformant en une matrice 3x3 :
dot = x1 * x2 + y1 * y2 + z1 * z2 det = x1 * y2 * zn + x2 * yn * z1 + xn * y1 * z2 - z1 * y2 * xn - z2 * yn * x1 - zn * y1 * x2 angle = atan2(det, dot)
Pour que ce calcul soit valide, le vecteur normal n doit être normalisé à l'unité longueur.
Alternativement, le déterminant peut être exprimé sous la forme d'un produit triple :
det = n · (v1 × v2)
Cette approche peut être plus simple à implémenter dans certaines API et donne un aperçu de la mécanique sous-jacente : le produit vectoriel est proportionnel au sinus de l'angle et est perpendiculaire au plan, ce qui signifie qu'il est un multiple de n. Le produit scalaire mesure donc essentiellement la longueur de ce vecteur avec le signe correct appliqué.
Plage 0 – 360°
La plupart des implémentations atan2 renvoient des angles dans la plage [-π, π] en radians ou [-180°, 180°] en degrés. Pour obtenir des angles positifs compris entre [0, 2π] ou [0°, 360°], la transformation suivante peut être appliquée :
dot = x1 * x2 + y1 * y2 # Dot product between [x1, y1] and [x2, y2] det = x1 * y2 - y1 * x2 # Determinant angle = atan2(det, dot) # atan2(y, x) or atan2(sin, cos)
Alternativement, l'expression suivante évite la distinction des cas :
dot = x1 * x2 + y1 * y2 + z1 * z2 # Between [x1, y1, z1] and [x2, y2, z2] lenSq1 = x1 * x1 + y1 * y1 + z1 * z1 lenSq2 = x2 * x2 + y2 * y2 + z2 * z2 angle = acos(dot / sqrt(lenSq1 * lenSq2))
Cette technique de correction ne se limite pas à ce problème spécifique mais peut être appliquée à tout scénario impliquant atan2.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!