Это делает трюк:
atan2(sqrt(dot(cross(a, b), cross(a, b))), dot(a, b))
как лямбда-функция Python:
import math, numpy
angle = lambda a, b: math.atan2(
math.sqrt(
numpy.dot(*([numpy.cross(a, b)]*2))
),
numpy.dot(a, b)
)
результаты приведены в радианах:
In : angle([1.,1.,1.], [-1.,1.,1.])
Out: 1.2309594173407747
In : angle([0.,1.,0.], [0.,0.,1.])
Out: 1.5707963267948966
работает в 2-х измеренияха также:
In : angle([0.,1.], [1.,0.])
Out: 1.5707963267948966
In : angle([0.,1.], [1.,1.])
Out: 0.7853981633974483