Get negative and positive angles from 2 vectors where vector1 is 0

Hello,

Iv found loads of threads on this topic but after days of trying I still can’t seem to get my head around it.

I have 3 points, the first 2 points remain stationary and the 3 point moves. I want to know what angle the 3rd point is at relative to the first 2 points. So far I can get the first 2 points to be my 0 angle but the 3rd point only returns positive angles. Then I tried converting to radians then back to degree’s but I’m not fully understanding it.

Iv attached a picture to hopefully help explain what I’m aiming for.

Here’s my code so far:

Vector2 zeroAngle = secondPosition.transform.position - firstPosition.transform.position;
        float thirdPositionAngleAngle = Vector2.Angle(zeroAngle, secondPosition.transform.position - thirdPositionAngleAngle.transform.position);
        float radConvertion = thirdPositionAngleAngle * Mathf.Deg2Rad;
        thirdPositionAngleAngle = radConvertion * (180 / Mathf.PI);

Any help would be fantastic.

Alex

2477493--170704--Angle Question.png

First off, you’re 3rd and 4th line are completely useless:

float radConvertion = thirdPositionAngleAngle * Mathf.Deg2Rad;
thirdPositionAngleAngle = radConvertion * (180 / Mathf.PI);

You literally just converted degrees to radians, and than back to degrees.

As for these 2 lines:

Vector2 zeroAngle = secondPos - firstPos;
float thirdPositionAngleAngle = Vector2.Angle(zeroAngle, secondPos - thirdPos);

Vector2.Angle finds the nearest angle between 2 vectors. So you’re not going to get negative or positive angles. You’ll get an angle between 0 and 180.

Also vectors have direction! When you subtract to positions you get a vector from one to the other.

V = B - A

V will be a vector from A to B.

You’re getting vectors from ‘first’ to ‘second’, and from ‘third to second’. If the 3 points created a straight line like the upper left in your image, you’d get 180 degrees, because they travel in opposite directions.

To get that image to be 0 degrees, you have to make sure you go in order:

Vector2 vA = secondPos - firstPos;
Vector2 vB = thirdPos - secondPos;
float angle = Vector2.Angle(vA, vB);

Now this will give you the angle, but it’ll be positive.

You also want sign to denote angular direction off vA. Does vB rotate clockwise OR counter-clockwise off vA.

In your image it appears you want +/positive to mean counter-clockwise, and -/negative to mean counter-clockwise.

To do this we need another vector that we KNOW the direction of off of vA. We can do that by rotating it 90 degrees in the desired direction.

Vector2 tang = new Vector2(-vA.y, vA.x);

This formula actually generates a vector rotated 90 degrees counter-clockwise off of vA.

2477533--170708--direction_of_angle.png
In this image:
vA is the black arrow
vB is the blue arrow, and the green is another alternate arrow if we the ‘thirdPos’ went a different direction
tang is the red arrow, vA rotated 90 degrees counter-clockwise

Now there’s another operation, it’s called the ‘dot product’. This operation projects one vector onto another, if the second were a unit vector it’d give the length along that axis. We don’t care about the length though, we just care about the direction. See if the projection goes the opposite direction of the axis vector it’ll be negative (the green arrow would result in negative values), but in the same direction it’ll be positive (blue arrow would result in positive values).

So now we can get the direction:

float dir = Mathf.Sign(Vector2.Dot(vB, tang));
angle *= dir;

Because we know that ‘tang’ is counter-clockwise from vA, we know that positive means counter-clockwise. So just apply that sign to the angle.

All together it is:

Vector2 vA = secondPos - firstPos;
Vector2 vB = thirdPos - secondPos;
float angle = Vector2.Angle(vA, vB);

Vector2 tang = new Vector2(-vA.y, vA.x);
float dir = Mathf.Sign(Vector2.Dot(vB, tang));
angle *= dir;

You can find this generalized in my VectorUtil class here:

see the function ‘AngleOff’

3 Likes

What you did is right, just add this line of code and it should work:

Vector2 vec1 = firstPosition.transform.position;
Vector2 vec2 = secondPosition.transform.position;
Vector3 vec3 = thirdPosition.transform.position;

//<--- your code goes here

thirdPositionAngle *= Mathf.Sign( (vec2.x - vec1.x) * (vec3.y - vec1.y) - (vec2.y - vec1.y) * (vec3.x - vec1.x) );

Formula for this is found on:
http://stackoverflow.com/questions/1560492/how-to-tell-whether-a-point-is-to-the-right-or-left-side-of-a-line

1 Like

Thanks to both of you. I now have a much better understanding and all is working exactly how I wanted. Really appreciate your time.