Emacs Calc: Angle Between Vectors

In my geometry studies, I learned that one can get the angle between two vectors with this formula:

cos \theta = \frac{V_1 \cdot V_2}{| V_1 | | V_2 |}

I.e., the cosine of the angle equals the dot product of the two vectors over the product of their magnitudes.

Here we get about 1.05 radians or about 60.26 degrees. A cool thing about this formula is it works for vectors of any (matching) dimension, i.e., 3-D coordinates, 4-D coordinates, etc.

This is definitely doable in Emacs Calc, since we have a dot product function, called inner-product (press ‘x inner product’), But doing the angle formula involves a lot of steps, with either stack rotation or storing the vectors in variables. So I wanted to get the angle formula stored as a calc formula. Unfortunately, inner-product itself is only an interactive function, so this was problematic. However, inner-product actual calls another function, inner. So, this formula is possible:

arccos(inner(mul, add, v1, v2) / (abs(v1) abs(v2)))

How do you store this formula in Emacs? I could walk you through the steps described in section 18.4 of the Emacs Calc info manual, but the end result is that this code is stored in your ~/.emacs.d/calc.el:

(put 'calc-define 'calc-vectorsangle '(progn
 (defun calc-vectorsangle nil (interactive) (calc-wrapper (calc-enter-result 2 "vect" (cons (quote calcFunc-vectorsangle) (calc-top-list-n 2)))))
 (put 'calc-vectorsangle 'calc-user-defn 't)
 (defun calcFunc-vectorsangle (v1 v2) (math-normalize (list (quote
  calcFunc-arccos) (list (quote /) (list (quote calcFunc-inner) (quote
  (var mul var-mul)) (quote (var add var-add)) v1 v2) (list (quote *)
  (list (quote calcFunc-abs) v1) (list (quote calcFunc-abs) v2))))))
 (put 'calcFunc-vectorsangle 'calc-user-defn '(calcFunc-arccos (/
  (calcFunc-inner (var mul var-mul) (var add var-add) (var v1 var-v1)
  (var v2 var-v2)) (* (calcFunc-abs (var v1 var-v1)) (calcFunc-abs (var
  v2 var-v2))))))
 (define-key calc-mode-map "zA" 'calc-vectorsangle)
))

Then when you start calc, you can put two vectors on the stack, and enter command ‘x vectorsangle’ or ‘z A’ for short:

This will work for vectors with as many more coordinates as you want, so long as there are the same number in each vector.

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s