Archived

This topic is now archived and is closed to further replies.

EGD Eric

Finding the angle between two vectors

Recommended Posts

Here's what I'm doing: //Finding the DotProduct float Vector2D::DotProduct(Vector2D &someVector) { return x * someVector.x + y * someVector.y; } float Vector2D::InnerAngle(Vector2D &someVector) { float Angle = 0; //find the dot product of 2 normalized vectors to get //the inner angle Vector2D me_Normalized = FindUnitVector(); someVector.normalize(); Angle = me_Normalized.DotProduct(someVector); //convert to radians, because C math functions //only take radians Angle = Angle * PI /180; Angle = acos(Angle); //convert angle back to degrees Angle = Angle * 180/PI; return Angle; } Edit: God, I'm absent minded today. I forgot to mention what the problem was! Its not returning the right number. Always returns something between between 81 and 89 [edited by - EGD Eric on January 24, 2004 4:40:12 PM] [edited by - EGD Eric on January 24, 2004 5:25:06 PM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
quote:
Original post by EGD Eric
Angle = Angle * PI /180;
Angle = acos(Angle);


acos() doesn''t take an angle, it RETURNS an angle. Thus no conversion before the call.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
in fact the dot product gives "cos(angle)" so there''s no meaning to convert a cosinus in radian...

Share this post


Link to post
Share on other sites
I''m just following these steps because a book says that''s how to do it.

It says this:

cos = (A . B ) / (|A| * |B|)

the pipe symbols (|A|) mean length. A . B means the Dot product.

It says that if A and B are normalized (have length of 1) then the equation is simplified:

cos = (A . B) / (1 * 1)

cos = A . B

So from there I should get the cosine or arccosine (cos -1) to get the angle, right? So to do that, I''ve got to call the accos or cos function. But C math functions take radians, not degrees. So I convert to radians to let C math do its thing, then revert it back to degrees, a measurement that I understand.


I was never any good at math, especially trig. Can you tell me in the simplest possible way, what I need to do to get the angle between 2 vectors?

Share this post


Link to post
Share on other sites
>> cos = (A . B ) / (|A| * |B|)

better: cos a = (A . B ) / (|A| * |B|) where a is your angle.

a = arccos(cos a) because arccos is the inverse function of cos (within limits)

so:
a = arccos(cos a) = arccos [ (A . B ) / (|A| * |B|) ]

as you already mentioned a will be in radians, so you might want to convert it to degrees of angle if you feel you need that.

One other thing: Consider overloading the operator* with the dot product so Vector1.DotProduct(Vector2) => Vector1*Vector2. It doesn´t have any impact on your code but imho it looks better (since it´s closer to the mathematical expressions).

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
One more thing. Get used to working with radians instead. It simplifies the code and makes it less prone to errors like the above.

Share this post


Link to post
Share on other sites

float angle(float ax, float ay, float bx, float by)
{
float result;
float dx=bx-ax;
float dy=by-ay;
result = (atan2(dx , dy)) * 180 / 3.14;
result = result - 90;
if (result < 0)
{
result = result + 360;
}
return result;
}


That''s what I use.

Share this post


Link to post
Share on other sites
But I don't understand, Atheist, from what you and the book are telling me, what I'm doing should be working.

Sure, I'll overload that operator. Might as well.

You're right, anonymous, Radians are better. Problem is, I'm making this game in OpenGL, which uses degrees.

Edit: I tried using your code, Jack, it doesn't give me an accurate angle.

Edit: again: Ok, how are you guys putting in text boxes?

[edited by - EGD Eric on January 24, 2004 7:49:47 PM]

[edited by - EGD Eric on January 24, 2004 8:33:55 PM]



[edited by - EGD Eric on January 24, 2004 8:35:29 PM]

Share this post


Link to post
Share on other sites
the problem with your code is that the result of the dotproduct is NOT an angle at all. only when you take the arccosine of it you will get an angle. in radians. you can scale that value to degrees if you like. just dont do any scaling on the dotproduct outcome.

Share this post


Link to post
Share on other sites
1
------
angle = acos(A.Dot(B)) * 180.0f / Pi;

assuming A and B are normalised

that will give you the angle in the range [0, 180]



2
------
float dot = A.x * B.x + A.y * B.y;
float cross = A.x * B.y - A.y * B.x;

angle = (atan2(cross, dot) * 180.0f / Pi) + 180.0f;

A and B do not need to be normalised. it will return the angle in the range [0, 360].


I think Jack got it wrong.

Share this post


Link to post
Share on other sites
Allright, I''ve got er working now. And I understand trig a little better too. You''ve all been telling me over and over, and I just wasn''t getting it: acos does not take an angle, it takes a ratio between two sides of a triangle! Thank you for your patience everyone!

Share this post


Link to post
Share on other sites
quote:
Original post by Anonymous Poster
And don''t bother with jack_1313''s code. It won''t give you the angle between vector a and b.



Gives the angle between two points. It works well enough for me. What is wrong with it?

Share this post


Link to post
Share on other sites
Jack, I hope you understand what an angle between two POINTS means for you. How would you define it ? In math it means nothing. It''s not hard to see you only compute the angle between vector AB and the X axis.

Damn many should stop trying to code any GL or 3D and go back to school. You need 1000 times more math skills to do anything valuable in 3D programming. Always the same ultra noob posts here, again and again ... This saddens me about Gamedev.

For 3D noobs like Eric :

Stage 1 Learn basic calculus and geometry before attempting any GL.

Stage 2 Google search before poluting the forums with such noob questions (1).

Stage 3 THEN come here and post in the math threads.

(1) At its current rate of propagation, the noob threads polution will start to make the search engine bots dizzy. As a consequence, very soon those who''ll try to get valuable information will be lost into a sea of www garbage. In short : Don''t ask stupid questions when you already know a way to find the answer.

K anyone has to start, and I don''t blame anyone for that. But don''t count on others for "homework" then, specially when there is so much freely available on the most serious side of the www.

Share this post


Link to post
Share on other sites
quote:
Original post by Charles B
Jack, I hope you understand what an angle between two POINTS means for you. How would you define it ? In math it means nothing. It''s not hard to see you only compute the angle between vector AB and the X axis.

Damn many should stop trying to code any GL or 3D and go back to school. You need 1000 times more math skills to do anything valuable in 3D programming. Always the same ultra noob posts here, again and again ... This saddens me about Gamedev.



Sorry, I merely missunderstod the question... partially because I didn''t bother to read it properly . Ooops.

Share this post


Link to post
Share on other sites
I''m having a problem with this code:

return atan2(cross(v1, v2).len(), dot(v1, v2));

Seems like len() would always return a positive number right? Calculating a length with the Pythagorean Theorem is always positive. And as a result wouldn''t atan2() always return a positve angle (0 thru +180)? When what pretty much everyone in the world is going to want is an angle in the full 360 range of (-180 thru +180)?

I''ve spent hours on Google trying to find the stupid angle between two vectors. No I don''t want the angle that I would have gotten if both vectors had been the the same quadrant, I want the actual angle between the two actual vectors whether or not they are in the same quadrant. Sorry for venting, just can''t understand why so many people post incomplete "answers" on the internet without realizing they are screwing up all the newbies. (Yes I know they probably did post for free but: do it right or don''t do it at all).

I''m not picking on minorlogic. His is by far the best answer I''ve found on at least two dozen sites claiming to have the answer. All the other "answers" I found were in (0 thru +90) or perhaps (-90 thru +90) only. Maybe he just made a small mistake or maybe I''m missing something basic. BTW I''m using left-handed coordinates if that matters. Here is some of my basic code:

cross product: (left-handed)
C[0] = ((A[1]*B[2])-(B[1]*A[2]));
C[1] = ((A[2]*B[0])-(B[2]*A[0]));
C[2] = ((A[0]*B[1])-(B[0]*A[1]));

cross product: (right-handed, I think, not really using this)
C[0] = -((A[1]*B[2])-(B[1]*A[2]));
C[1] = -((A[2]*B[0])-(B[2]*A[0]));
C[2] = -((A[0]*B[1])-(B[0]*A[1]));

dot product:
dot = (A[0]*B[0])+(A[1]*B[1])+(A[2]*B[2]);

length of vector:
length = sqrt((A[0]*A[0])+(A[1]*A[1])+(A[2]*A[2]));



The examples I found for left-handed cross product code were almost as bad as the angle between two vectors code, so I wouldn''t be surprised if I have something wrong in there.

Thanks in advance if anybody can clear up my confusion!

Share this post


Link to post
Share on other sites
quote:

And as a result wouldn't atan2() always return a positve angle (0 thru +180)? When what pretty much everyone in the world is going to want is an angle in the full 360 range of (-180 thru +180)?
[...]
Maybe he just made a small mistake or maybe I'm missing something basic.


Maybe you´re missing that the angle between two 3D vectors cannot be greater than 180° unless you add additional conditions to your "angle".


Let me try to explain what I mean:

In 2D you can in fact define an angle a in the range 0°<=a<360° between two non-colinear vectors u and v. But therefore you need to add further conditions like "I´m starting from u (static arm of angle) rotating counter-clockwise until I reach v (free arm of angle)". <= hope that "static arm of angle" and "free arm of angle" are the correct english expressions for what I meant.

In 3D you´ll have to find analogies to above conditions that one usually doesn´t introduce due to lack of need. Defining a static and a free arm of angle is simple but when it comes to defining a "direction of rotation" you can run into trouble:
In 3D you rotate around a vector. The line defined by the vector is your axis of rotation. Its orientation on the line gives you the "orientation" of your rotation (analogon to clockwise and counter-clockwise). How do you want to distinguish one orientation from the other without further assumptions? One idea would be to say "I rotate around the vector v = u x v (cross product)". This is what you usually do and it turns out that in that case you just need angles in the range (0, 180) because the cross product changes it´s sign at u = -v and hence your "orientation" on your axis of rotation changes (=> you´ll rotate the other way round).

If you´re able to distinguish one orientation from the other (say if you have a plane that both vectors are on with a well defined plane normal n that you rotate around) then it might make sense to define an angle in the range (-180, 180]. In that case you can check the sign of (u x v)*n and change the sign of the angle if needed.
I can´t imagine much use for this right now but there might be.


Resume: You usually only need the angle in the range [0, 180).

[edited by - Atheist on February 12, 2004 11:11:13 PM]

Share this post


Link to post
Share on other sites
OK I think I see what you are saying.

More information:

I have two 3D vectors. I have one of their two cross products.

When rotating around a cross-product (IIRC) postive angles are counter-clockwise and negative angles are clockwise. Maybe I have it backwards, but I know it has to be one way or the other.

Now I want to rotate one of the vectors arbitrarily within +180 thru -180. Before I can do this, I have to know how far away the other vector is. How far away = an angle = measured from +180 to -180. It''s like one vector is fixed on the circle and I''m trying to find out if the other is on the positive or negative "side" of that circle.

So how do I do that while getting the size of the angle too?


Thanks!

Share this post


Link to post
Share on other sites
Oh wait: did you just say that the cross product flips when one of the vectors changes sides of the circle? That could possibly explain why I''m so confused. But I''m not even sure I understood your explaination now.

Share this post


Link to post
Share on other sites
What I basically said is that you can´t really distinguish clockwise from counter-clockwise in 3D (looking at a clock from behind will make it go counter-clockwise), so unless you have an additional information like "I´m looking into direction n" (where n is a view direction instead of a plane normal but works the same way except that u x v can be perpendicular to n) you cannot define a direction of rotation.

Further note: You don´t even have to rotate around a vector perpendicular to u and v to rotate u on v. You can also rotate around normalized(u)+normalized(v) in which case the rotation angle will always be 180°.

Share this post


Link to post
Share on other sites
I suddenly realized that OF COURSE the cross product flips when the free vector crosses to the other side of the static vector. Because: I already knew that''s how you get the other of the two cross products, is you reverse the vectors in the cross operation.

I feel like I almost have my answer but I haven''t figured out what you mean by "you can check the sign of (u x v)*n". What is n? How can a cross product (the "(u x v)" part) have a sign to check?

Share this post


Link to post
Share on other sites
more information:

I'm programming in OpenGL which I believe defines that when you are looking down the positive half of an axis, then positive angles rotate clockwise and negative angles rotate counter-clockwise. (Had that backwards before I think).

Vector AA( 1.0, 0.0, 0.0 ); // example values
Vector BB( -1.0, -1.0, 0.0 ); // example values
Vector CC;
CC = cross(AA,BB);

Now at this point I need to get the angle between AA and BB. Using minorlogic's formula I can get the correct angle but sometimes it has the wrong sign.


[edited by - sparkster on February 12, 2004 12:38:50 AM]

Share this post


Link to post
Share on other sites
maybe less related to the topic, remember to add

if (cosval>1.0f) cosval=1.0f;
else if (cosval<-1.0f) cosval=-1.0f;

before

float angle=acos(cosval);

maybe you''ll say that the dot product of two normalized vectors will never get a value out of [-1.0,1.0], but i''ve got such things happen and get an illegal "angle". this bug is hard to find. so remember to add it.

Share this post


Link to post
Share on other sites