Calculate the angle between two 3D vectors


Note: I have absolutely no clue about Vector math, especially not in 3D.

I am currently working on some Javascript code that determines if a Finger that got captured by a Leap Motion Controller is extended (i.e. completely straight) or not.

Leap Motion provides us with an API that gives us Object for Hands, Fingers and Bones. Bones in particular have several properties, such as position Vectors, direction Vectors and so on, see here for the Documentation.

My idea was to take the Distal Phalang (tip of your finger) and Proximal Phalang (first bone of your finger), calculate the angle between them by getting the dot product of the two direction Vectors of the bones and then decide if it is straight or not. Like this, essentially:

var a = hand.indexFinger.distal.direction();
var b = hand.indexFinger.proximal.direction();
var dot =,b);
var degree = Math.acos(dot)*180/Math.PI;

The issue here is that these values are not reliable, especially if other fingers move about. It seems like the direction Vectors of the bones change when other fingers change direction (???).

For example, when all my Fingers are extended, the value of degree is roughly 0 and fluctuates between -5 and 5. When I make a fist, the value shoots up to 10, 15, 20. Logging the values of the direction Vectors reveals that they indeed do get changed, but how does this make sense? The Finger doesn't move, so its direction should stay the same.

Even worse for the thumb, the values don't add up there at all. An extended thumb can get values similar to the IndexFinger, but rotation the thumb upwards or downwards has changes in the range of 60 degrees!

I've tried using positional values instead, which gives me NaN results because the values seem to be to big.

So, my question is: how could I reliably calculate the angle between two Vectors? What am I missing here?

The correct formula is

cos(angle) = dot(a,b)/(norm(a)*norm(b))

where norm is the euclidean norm or length.

You should have gotten a wrong result, but the lengths of a and b should be constant, so the result should have been consistently wrong…