Les Angles entre deux n-dimensions des vecteurs en Python
J'ai besoin pour déterminer l'angle(s) entre deux n-dimensions des vecteurs en Python. Par exemple, l'entrée peut être deux listes comme suit: [1,2,3,4]
et [6,7,8,9]
.
- C'est la meilleure réponse est @MK83 car c'est exactement l'expression mathématique theta = atan2(u^v, u.v). même le cas où u=[0 0] et v=[0 0] est couvert car c'est seulement de temps atan2 de produire l'NaN dans les autres réponses NaN seront produits par l' / norm(u) ou / norm(v)
Vous devez vous connecter pour publier un commentaire.
Note: on va à l'échec lorsque les vecteurs ont la même ou la direction opposée. La mise en œuvre correcte est ici: https://stackoverflow.com/a/13849249/71522
math.sqrt(x)
est équivalent àx**0.5
etmath.pow(x,y)
est équivalent àx**y
, je suis surpris de ces ont survécu à la redondance de l'axe de brandir au cours de l'Python 2.x->3.0 transition. Dans la pratique, j'ai l'habitude de faire ces sortes de numérique choses comme partie d'un plus grand calcul intensif processus, et l'interprète de soutien pour les '**' aller directement sur le bytecode BINARY_POWER, par rapport à la recherche de "mathématiques", l'accès à son attribut 'sqrt', puis la lente et douloureuse bytecode CALL_FUNCTION, peut apporter une amélioration mesurable de la vitesse à aucun codage ou la lisibilité des coûts.angle((1., 1., 1.), (1., 1., 1.))
). Voir ma réponse un peu plus la version correcte.(1., 1., 1.)
,(1., 1., 1.)
évidemment non nulle des grandeurs, mais les résultats de calcul dansnan
...acos
etasin
ne sont pas numériquement stable pour certaines valeurs. Pourquoi personne ne l'enseigner plus?Note: toutes les autres réponses ici échouera si les deux vecteurs ont la même direction (ex,
(1, 0, 0)
,(1, 0, 0)
) ou des directions opposées (ex,(-1, 0, 0)
,(1, 0, 0)
).Voici une fonction qui va gérer correctement ces cas:
np.isnan
au lieu de celui de la bibliothèque de mathématiques? En théorie, elles devraient être identiques, mais je ne suis pas tout à fait sûr dans la pratique. De toute façon, j'imagine qu'il serait plus sûr.np.isnan
va faire quelque chose de raisonnable si l'entrée est un tableau, qui ne sera jamais le cas ici. Cependant, l'utilisation denp.isnan
serait certainement plus propre (je ne sais pas pourquoi j'ai utilisémath.isnan
...), donc je vais passer ça.arccos
directement et en toute sécurité. : Dans [140]: np.arccos(np.point(np.array([1,0,0]),np.array([-1,0,0]) )) Out[140]: 3.1415926535897931 Dans [141]: np.arccos(np.point(np.array([1,0,0]),np.array([1,0,0]) )) Out[141]: 0.0unit_vector
. Une possibilité est de simplement retourner le vecteur d'entrée dans cette fonction lorsque c'est le cas.nan
si vous utilisez aléatoire de vecteurs unitaires qui arrive d'avoir un produit de 1. En raison de à virgule flottante de précisiondot()
serait de retour1.0000000000000002
. Cela est vrai même pour la version 1.16.1.À l'aide de numpy (fortement recommandé), vous feriez:
nan
) lorsque la direction de deux vecteurs est soit identique ou opposé. Voir ma réponse pour une version correcte.angle = arccos(clip(c, -1, 1))
pour éviter l'arrondi. Cela résout @DavidWolever s 'question.clip
devrait être ajouté à la liste de numpy importations.L'autre possibilité est d'utiliser seulement
numpy
et il vous donne l'angle intérieuret voici le résultat:
Si vous travaillez avec des vecteurs 3D, vous pouvez le faire de manière concise à l'aide de la toolbelt vg. C'est une légère couche sur le dessus de numpy.
Vous pouvez également spécifier un angle de vue de calculer l'angle de via de projection:
Ou de calculer la signature de l'angle de la via de la projection:
J'ai créé la bibliothèque lors de mon dernier démarrage, où elle a été motivée par utilise comme ceci: des idées simples qui sont prolixes ou opaque dans NumPy.
Pour les quelques-uns qui peuvent avoir (en raison de RÉFÉRENCEMENT de complications) est terminé ici à essayer de calculer l'angle entre deux lignes en python, comme dans
(x0, y0), (x1, y1)
de lignes géométriques, il y a le ci-dessous minimale solution (utilise leshapely
module, mais peut être facilement modifié et non à):Et l'utilisation serait
Utilisation de numpy et de prendre soin de la largeur de bande interdite du les erreurs d'arrondi:
Remarque, cette fonction renvoie une exception si l'un des vecteurs est de magnitude zéro (division par 0).
David Wolever de la solution est bon, mais
Si vous voulez avoir signé angles vous devez déterminer si une paire est droitier ou gaucher (voir wiki pour plus d'info).
Ma solution est la suivante:
Il n'est pas parfait à cause de cette
NotImplementedError
mais pour mon cas il fonctionne bien. Ce comportement pourrait être fixe (cause handness est déterminé pour chaque paire), mais il faut plus de code que je veux et dois écrire.