sseal
sseal

Reputation: 9

Angle between vectors - Python

I am a beginner in Python (a reeeal beginner) but I have a few assignments to do and I’m totally stuck with one problem. I have to count an angle between vectors. I’ve spent tons of nights trying to do that and I actually even wrote code, but. It shows only positive numbers, so it doesn’t count any negative values. How can I change it?

My data consists of eye-tracking coordinates so I’m sure there must be negative values. Sample data - {308, 394, 700, 738.6, 298.8}, {554, 718, 1270, 737.3, 352.5}, {300, 1314, 1612, 1014.3, 728.5}, {316, 1642, 1956, 844.5, 885.1}, where first 4 values are coordinates (x1, x2, y1, y2). Code I have:

def angle_between(v1, v2, deg=True):
""" Returns the angle in radians between vectors 'v1' and 'v2'::
"""
print('First vector:', v1)
print('Second vector:', v2)

v1_u = unit_vector(v1)
v2_u = unit_vector(v2)

radians = np.arccos(np.clip(np.dot(v1_u, v2_u), -1.0, 1.0))
result = radians

# print('radians:', result)
if deg:
    result = np.degrees([radians.real])[0] 
    print(f"degrees: {result}")
return result

Help me pls! :(

Upvotes: 0

Views: 1868

Answers (3)

MBo
MBo

Reputation: 80287

To get full circle range, use arctan2

radians = np.arctan2(np.cross(v1_u, v2_u), np.dot(v1_u, v2_u))

This approach gives angle needed to rotate the first vector to make the same direction as the second one, so it describes mutual orientation of vectors (what one is "left" or counter-clockwise, for example)

Upvotes: 4

Guilhem L.
Guilhem L.

Reputation: 421

Actually, that's not so a coding problem but a math problem. Not sure that's the best place to solve, I let someone more experimented to erase/deplace if any necessity.

Arc cosinus gives you a number between 0 and pi, so you can't hope to obtain an oriented angle. You need to make a distinction between negative and positive scalar product.

Let'go on on step by step.

let's first define the following function, we suppose v1 and v2 normalized for the sake of simplicity

def angle(v1,v2):
    scalar_product = v1[0]*v2[0] + v2[1]*v2[1]
    return npy.arccos( scalar_product ) # result between 0 and pi

If we setv1 = [ 1 , 0 ] and try

angle( v1 , [ np.cos(2*np.pi/3) , np.sin(2*pi/3) )
angle( v1 , [ np.cos(4*np.pi/3) , np.sin(4*pi/3) )

You have the same result, around 2.09, so 2*pi/3. As 2*pi/3 and 4*pi/3 have the same cos, you can't grab the difference.

So we need information from the determinant of the matrix composed of the two vectors to determine the orientation. You can use np.linalg.deton the matrix you build with the two vectors. If the determinant is positive, you keep the angle you found with the function angle, else you take the opposite. Should do the work.

Upvotes: 0

Noel93
Noel93

Reputation: 156

From my understanding the arccos function only returns values between 0 and Pi, so you won't find any negative numbers there.

Upvotes: 2

Related Questions