Skip to main content
GameDev.net gamedev.net
🔒 Locked

Angle between two vectors

Started by steg Nov 3, 2004 at 4:38 AM 17 replies 3.1k views
Original Post
steg
steg
Hi all, I suppose this is really simple but my brain is not working today. If I have the following vectors : Start point for both vectors is : ( 24, 24 ) and endpoints are : A=( 45, 27 ) and B=( 15, 39 ), how can I determine the angle between them, I need this in order to rotate vector A to vector B. Any help is much appreciated. Thanks, Steve
If it isn't working, take a bath, have a think and try again...
rick_appleton
rick_appleton
angle = acos(A dot B)

this gives the same angle for a righthand rotation and a lefthand rotation. You can find the direction by calculating the cross-product between the two and comparing it with the two vectors.
steg
steg
Thanks Rick,

This is what I put in code :

double DotProduct = ( m_X2 * pt.x ) + ( m_Y2 * pt.y );double angle = acos( DotProduct );


But I'm getting -1 all the time ? Is this wrong ?

Thanks,
Steve

PS - I did try this :

int EndX = m_X2 - pt.x;int EndY = m_Y2 - pt.y;double angle = atan2( EndY, EndX );



If it isn't working, take a bath, have a think and try again...
wanzi
wanzi
You need to normalize the two vectors before performing dot product in order to get correct answer.
As dot(A, B) = |A||B|*cos(theta), after normalizing, because |A|=|B|=1, then dot(A, B) = cos(theta).
rick_appleton
rick_appleton
First of all, wanzi is correct, A and B should be unit vectors.

Second, my use of A and B was misleading. They are vectors, not points. Your A and B are points. Therefore:

myA = yourA - startingpoint
myB = yourB - startingpoint
steg
steg
Ok,

So say I want to get the unit vector for A :

float StartEndX = m_X2 - 24;float StartEndY = m_Y2 - 24;float LenA = sqrt ( StartEndX * StartEndX + StartEndY * StartEndY );float UnitAX = StartEndX / LenA;float UnitAY = StartEndY / LenA;


Is this correct ?

Thanks again,
Steve
If it isn't working, take a bath, have a think and try again...
steg
steg
Thanks Rick,

This is what I have, but the line will only rotate from 0 to 180 ?

			float StartEndX = m_X2 - 24;			float StartEndY = m_Y2 - 24;			float MouseEndX = pt.x - 24;			float MouseEndY = pt.y - 24;			float Len = sqrt ( StartEndX * StartEndX + StartEndY * StartEndY );			float UnitX = StartEndX / Len;			float UnitY = StartEndY / Len;			float LenMouse = sqrt( MouseEndX * MouseEndX + MouseEndY * MouseEndY );			float UnitMouseX = MouseEndX / LenMouse;			float UnitMouseY = MouseEndY / LenMouse;			double DotProduct = ( ( UnitX * UnitMouseX ) + ( UnitY * UnitMouseY ) );			double cangle = acos( DotProduct );			cangle = cangle * R_to_D;			m_fAngle = cangle;                        RotateLine();


Could I mention the fact that vector B is the position of the mouse in client coordinates, i.e. :

GetCursorPos( &pt );
ScreenToClient( &pt );

Thanks for your help,
Steve
If it isn't working, take a bath, have a think and try again...
rick_appleton
rick_appleton
Yes, that is what I meant in my first post
 |           | |           | |           | \           /  \         /   \       /

both the above drawings give the same angle.
If you calculate the cross product of both vectors, that will give you the answer on which one of the two it is.

For 2D assume the third coordinate of both vectors is 0. However, we are only interested in the third coordinate of the resulting vector, so we only need to calculate that part of the cross product:

answer.z = a.x*b.y - a.y*b.x;

Then if answer.z is positive (and it should be near 1 if a and b are unit), it is one of the two solutions, and if it is negative, it is the other. I'm not sure which is which, just do a quick test.
steg
steg
Thanks again Rick,

I've added this code to get the Cross product :

float StartCrossX = m_X2 * pt.y;float StartCrossY = m_Y2 * pt.x;float CrossProduct = StartCrossX - StartCrossY;


I'm unsure what I do with the result ?

Kind regards,
Steve
If it isn't working, take a bath, have a think and try again...
rick_appleton
rick_appleton
Well I'm assuming you're moving your mouse about and can see the values changing?

If all went well CrossProduct should be almost 1 or almost -1.

If you start the mouse above the point (y is higher, is you assume y=0 at the bottom) and move it clockwise around the 24,24 you should see angle increasing from 0 to 180, while CrossProduct stays at either 1 or -1. When you go through the 180 deg (past 6 oclock), you'll see angle decreasing from 180 to 0, but CrossProduct will now have the other value than it had before you passed 180 deg.

This is all assuming either vector A or B is vertical.
steg
steg
Cross product varies between 0 to almost -1 dependent on where the mouse is.

Thus, this is where the positive and minus cross product values are :

minus | minus
----|----
pos | pos

So, if cross product is minus, I still don't know what to add to my angle ?

Kind regards,
Steve
If it isn't working, take a bath, have a think and try again...
steg
steg
Ok, I've come up with this code :

			if( CrossProduct < 0 && ( m_fAngle > 0 && m_fAngle < 90 ) )			{				// do something to angle? 							}			else				if( CrossProduct < 0 && ( m_fAngle > 90 && m_fAngle < 180 ) )				{                                  // do something to angle?				}


I don't know what I need to do to the angle ?

Thanks,
Steve
If it isn't working, take a bath, have a think and try again...
rick_appleton
rick_appleton
What kind of a program is it? glut? If it's something I could easily compile, could you post it somewhere, or send it to me (the source)? I have a feeling you misunderstood me somewhere, but I'm not sure where. If both vectors are unitlength, then the crossproduct.z should be either 1 or -1, not between 0 and 1.
steg
steg
Hi Rick,

The code is for a custom control in mfc, it is basically a round knob control which has a line running from the center of it which is the same size as the radius, this is vector A. The center being the start of the vector. Now, vector B is the mouse position, so moving the mouse left should rotate the line left as though you are turning the knob clockwise, does this make sense ?

Many thanks,
Steve

PS - the code is within a large project I have of which it needs many ocx to compile and run !
If it isn't working, take a bath, have a think and try again...
rick_appleton
rick_appleton
Ok, and should the line point at the mouse position, or should if only rotate the same amount as the mouse?

ps. If you use MSN add me to your list, it'll go faster than posting here.

edit: could you maybe post the entire code block?
rick_appleton
rick_appleton
Just to close this topic for the moment:

I was incorrect about the CrossProduct being 1 or -1. That is only true it the two vectors are prependicular already. The only thing needed about the CrossProduct is if it is positive or negative. Negative seems to denote CCW rotation, and positive CW rotation.

So:
if (cross>0)
angle = angle
else
angle = 360 - angle
steg
steg
Thanks for all your help Rick and everyone else.

This now works fine, I did use the dot product and the cross product.

Kind regards,
Steve

If it isn't working, take a bath, have a think and try again...

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.