Méthode numériquement stable de calcul des angles entre les vecteurs

14

Lors de l'application de la formule classique de l'angle entre deux vecteurs:

α=arccosv1v2v1v2

on constate que, pour des angles très petits / aigus, il y a une perte de précision et le résultat n'est pas précis. Comme expliqué dans cette réponse Stack Overflow , une solution consiste à utiliser l'arctangente à la place:

α=arctan2(v1×v2,v1v2)

Et cela donne en effet de meilleurs résultats. Cependant, je me demande si cela donnerait de mauvais résultats pour des angles très proches de π/2 . Est-ce le cas? Si oui, existe-t-il une formule pour calculer avec précision les angles sans vérifier la tolérance à l'intérieur d'une ifbranche?

astrojuanlu
la source
1
Cela dépendra de la mise en œuvre de la fonction tangente inverse à deux paramètres. Les versions lentes et stables basculent conditionnellement entre travailler avec x / y et y / x pour maintenir la précision, tandis que les versions rapides ne font que coller les choses dans le bon quadrant et ne sont donc pas plus précises que la version à un paramètre.
origimbo
Vous devez définir "perte de précision": supposez que la bonne réponse est et vous obtenez à la place . Avez-vous besoin de ou est suffisant? αα+ΔΔαΔπ
Stefano M
Dans ce cas, la bonne réponse était et j'ai obtenu , les deux . αα1081
astrojuanlu

Réponses:

18

( J'ai déjà testé cette approche et je me souviens qu'elle a fonctionné correctement, mais je ne l'ai pas testée spécifiquement pour cette question. )

Autant que je sache, les deux et peuvent souffrir d'une annulation catastrophique s'ils sont presque parallèles / perpendiculaires - atan2 ne peut pas vous donner une bonne précision si l'une des entrées est désactivée.v1×v2v1v2

Commencez par reformuler le problème en trouvant l'angle d'un triangle avec des longueurs de côté,et(ils sont tous calculés avec précision en arithmétique à virgule flottante). Il existe une variante bien connue de la formule de Heron en raison de Kahan ( zone de calcul et angles d'un triangle en forme d'aiguille ), qui vous permet de calculer la zone et l'angle (entre et ) d'un triangle spécifié par ses longueurs de côté, et le faire numériquement de manière stable. Étant donné que la réduction de ce sous-problème est également exacte, cette approche devrait fonctionner pour des entrées arbitraires.a=|v1|b=|v2|c=|v1v2|ab

Citant cet article (voir p. 3), en supposant , Toutes les parenthèses ici sont placées avec soin, et elles comptent; si vous vous retrouvez à prendre la racine carrée d'un nombre négatif, les longueurs latérales d'entrée ne sont pas les longueurs latérales d'un triangle.ab

μ={c(ab),if bc0,b(ac),if c>b0,invalid triangle,otherwise
angle=2arctan(((ab)+c)μ(a+(b+c))((ac)+b))

Le document de Kahan explique comment cela fonctionne, y compris des exemples de valeurs pour lesquelles d'autres formules échouent. Votre première formule pour est à la page 4.αC

La principale raison pour laquelle je suggère la formule de Heron de Kahan est parce qu'elle fait une très belle primitive — beaucoup de questions de géométrie planaire potentiellement délicates peuvent être réduites à trouver l'aire / l'angle d'un triangle arbitraire, donc si vous pouvez réduire votre problème à cela, il y a une belle formule stable pour cela, et il n'est pas nécessaire de trouver quelque chose par vous-même.

Modifier Suite au commentaire de Stefano, j'ai fait un tracé d'erreur relative pour , ( code ). Les deux lignes sont les erreurs relatives pour et , suivant l'axe horizontal. Il semble que ça marche. v1=(1,0)v2=(cosθ,sinθ)θ=ϵθ=π/2ϵϵentrez la description de l'image ici

Kirill
la source
Merci pour le lien et la réponse! Malheureusement, la deuxième formule que j'ai écrite n'apparaît pas dans l'article. En revanche, cette méthode peut devenir un peu complexe, car elle nécessite une projection en 2D.
astrojuanlu
2
@astrojuanlu Il n'y a pas de projection en 2D ici: quels que soient les deux vecteurs 3D, ils définissent un seul triangle (plan) entre eux - il suffit de connaître ses longueurs latérales.
Kirill
Tu as raison, mon commentaire n'a aucun sens. Je pensais en coordonnées plutôt qu'en longueurs. Merci encore!
astrojuanlu
2
@astrojuanlu Une dernière chose que je veux noter: il semble qu'il existe une preuve formelle que la formule de l'aire est exacte dans Comment calculer l'aire d'un triangle: une révision formelle , Sylvie Boldo , en utilisant Flocq.
Kirill
Excellente réponse, mais je conteste que vous pouvez toujours calculer avec précision en arithmétique à virgule flottante. En fait, si alors des annulations catastrophiques se produisent dans le calcul des composants de . cc<ϵmin(a,b)(v1v2)
Stefano M
7

La réponse efficace à cette question est, sans surprise, dans une autre note de Velvel Kahan :

α=2arctan(v1v1+v2v2,v1v1v2v2)

où j'utilise comme l'angle fait par avec l'axe horizontal. (Vous devrez peut-être inverser l'ordre des arguments dans certaines langues.)arctan(x,y)(x,y)

(J'ai donné une démonstration Mathematica de la formule de Kahan ici .)

JM
la source
Vous voulez dire ? arctan2
astrojuanlu
1
J'ai l'habitude de simplement décrire l'arctangente à deux arguments comme , oui. Dans une langue comme FORTRAN, l'équivalent serait . arctan(x,y)ATAN2(Y, X)
JM