Vector rotation and dot product question
I have two 2D vectors A and B and my goal is to rotate A so it faces in the same direction as B. I have computed the angle between the vectors using the dot product but I still need to find out whether the angle is negative or positive.
My question is this:
What is the simplest and most efficient way of finding out which way I need to rotate the vector?
I can think of three possible solutions:
1: Rotate vector A by the computed angle and check if the new vector is equal to the target vector B. If not, rotate the other way.
2: Check in which quadrant of the coordinate system vector A is located. Then check in which quadrant vector B is located. Depending on the quadrant of B the rotation direction can be discovered.
3: Use a hypothetical third axis and compute the cross product between vector A and B. The perpendicular vector will be either positive or negative depending on whether B is to the left or right of A. When rotating around that vector the rotation will always be in the right direction.
Any suggestions would be greatly appreciated.
Thx
#1 seems inefficient. #2 doesn't work. I suggest #3 -- it's trivial.
Just check the sign of xAyB-xByA. If it is negative, then your angle of rotation from A to B is negative.
Just check the sign of xAyB-xByA. If it is negative, then your angle of rotation from A to B is negative.
The easy way : atan2
The standard way uses these three steps (you search alpha):
1) dot prod, divide by the lengths (normas) and you get c=cos(alpha)
2) cross prod, divide by the lengths (normas) and you get s=sin(alpha)
3) atan2 gives you alpha = atan2(s,c)
Note that atan2 is as speedy as the acos you used (I suppose). Bur it's even better, you get rid of testing signs, and your code remains clear and concise.
Also note that you don't necessarilly have to define a rotation in the polar form (angle + scaling factor). You can also simply define a matrix, then you don't need any trigonometry, just linear algebra.
The standard way uses these three steps (you search alpha):
1) dot prod, divide by the lengths (normas) and you get c=cos(alpha)
2) cross prod, divide by the lengths (normas) and you get s=sin(alpha)
3) atan2 gives you alpha = atan2(s,c)
Note that atan2 is as speedy as the acos you used (I suppose). Bur it's even better, you get rid of testing signs, and your code remains clear and concise.
Also note that you don't necessarilly have to define a rotation in the polar form (angle + scaling factor). You can also simply define a matrix, then you don't need any trigonometry, just linear algebra.
Quote:Original post by Crazy Chicken
I have two 2D vectors A and B and my goal is to rotate A so it faces in the same direction as B.
My question is this:
What is the simplest and most efficient way of finding out which way I need to rotate the vector?
You have to rotate A around an extern axis (that is a vector pointing in/out from your plane) by an agle a.
If you know a to rotate a vector you can use the rotation matrix
| c s |R = | | where c = cos(a) and s = sin(a) | -s c |
and multiply A by R
R * A = (c*ax+ s*ay, c*ay - s*ax)
How to compute a ?
The angle you need can be computed from the scalar product ('dot')
i) A * B = (ax,ay)*(bx,by) = ax*bx + ay*by
but it is also
ii) A * B = |A|*|B|*cos(a)where |A| = sqrt(A*A) = sqrt(ax*ax+ay*ay) |B| = sqrt(B*B) = sqrt(bx*bx+by*by)
hence
cos(a) = A*B/(|A|*|B|)
that is
a = arcos((ax*bx+ay*by)/(|A|*|B|))
Rotate CW or CCW?
If you compute the extern product ('cross')
A x B = (ax,ay,az) x (bx,by,bz) = (vx,vy,vz)
where
az = 0bz = 0vx = ay*bz-az*by = 0 // right because v is 'extern'vy = az*bx-ax*bz = 0vz = ax*by-ay*bx
If vz is positive you have to rotate A counterclockwise(CCW), CW if vz is negative (this is the 'right hand rule').
if vz>0 rotate CCW by a else CW by a
Note1 : if vz = 0 -> a = 0° or 180°
Note2 : Charles is right too because |A x B| is also equal to
vz = |A x B| = |A|*|B|*sin(a) -> tan(a)=sin(a)/cos(a) -> compute a
Code
// returns the angle CCW needed to rotate A and make it parallel to Bfloat GetAngle(const Vector& A, const Vector& B){ float a = acos( (A*B)/(A.Len()*B.Len()) ); return( A^B>0 ? a : -a );}float Vector::Len(void)const{ return(sqrt((*this)*(*this)));}float Vector::operator * (const Vector& B)const{ return(x*B.x+y*B.y);}float Vector::operator ^ (const Vector& B)const{ return(x*B.y-y*B.x);}
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement