Direction of the shortest rotation between two vectors

my question is to design the direction of the smallest angle between two vectors in 2D. I am making a C ++ game where one of the obstacles is a rocket launcher for finding heat. I work by calculating the vector between the target and the bullet, normalizing the vector, and then multiplying it by speed. However, now I am returning to this class to make it better. Instead of instantly blocking the player, I want this to be done only when the bullet vector is at a certain angle (the angle between the bullet vector and the vector bulletloc-> target). Otherwise, I want him to slowly pan towards the goal by degrees, giving the player enough space to avoid this. I did all this (in the vb.net project so that I can simplify the problem, work through it and then write it in C ++). However, the bullet always rotates clockwise to the target, even if the fastest route is counterclockwise. Thus, the problem is to direct the direction of rotation so that the smallest angle is covered. Here is my code so you can try and see what I am describing:

Function Rotate(ByVal a As Double, ByVal tp As Point, ByVal cp As Point, ByVal cv As Point) 'params a = angle, tp = target point, cp = current point, cv = current vector of bullet' Dim dir As RotDir 'direction to turn in' Dim tv As Point 'target vector cp->tp' Dim d As Point 'destination point (d) = cp + vector' Dim normal As Point Dim x1 As Double Dim y1 As Double Dim VeritcleResolution As Integer = 600 tp.Y = VeritcleResolution - tp.Y 'modify y parts to exist in plane with origin (0,0) in bottom left' cp.Y = VeritcleResolution - cp.Y cv.Y = cv.Y * -1 tv.X = tp.X - cp.X 'work out cp -> tp' tv.Y = tp.Y - cp.Y 'calculate angle between vertor to target and vecrot currntly engaed on' Dim tempx As Double Dim tempy As Double tempx = cv.X * tv.X tempy = cv.Y * tv.Y Dim DotProduct As Double DotProduct = tempx + tempy 'dot product of cp-> d and cp -> tp' Dim magCV As Double 'magnitude of current vector' Dim magTV As Double 'magnitude of target vector' magCV = Math.Sqrt(Math.Pow(cv.X, 2) + Math.Pow(cv.Y, 2)) magTV = Math.Sqrt(Math.Pow(tv.X, 2) + Math.Pow(tv.Y, 2)) Dim VectorAngle As Double VectorAngle = Acos(DotProduct / (magCV * magTV)) VectorAngle = VectorAngle * 180 / PI 'angle between cp->d and cp->tp' If VectorAngle < a Then 'if the angle is small enough translate directly towards target' cv = New Point(tp.X - cp.X, tp.Y - cp.Y) magCV = Math.Sqrt((cv.X ^ 2) + (cv.Y ^ 2)) If magCV = 0 Then x1 = 0 y1 = 0 Else x1 = cv.X / magCV y1 = cv.Y / magCV End If normal = New Point(x1 * 35, y1 * 35) normal.Y = normal.Y * -1 cv = normal ElseIf VectorAngle > a Then 'otherwise smootly translate towards the target' Dim x As Single d = New Point(cp.X + cv.X, cp.Y + cv.Y) a = (a * -1) * PI / 180 'THIS LINE CONTROL DIRECTION a = (a*-1) * PI / 180 would make the rotation counter clockwise' 'rotate the point' dX -= cp.X dY -= cp.Y dX = (dX * Cos(a)) - (dY * Sin(a)) dY = (dX * Sin(a)) + (dY * Cos(a)) dX += cp.X dY += cp.Y cv.X = dX - cp.X cv.Y = dY - cp.Y cv.Y = cv.Y * -1 End If Return cv End Function 

One of my ideas was to develop a bearing for two vectors, and if the difference exceeds 180 degrees, turn clockwise, otherwise rotate counterclockwise, any ideas will be useful. Thanks.

EDIT: I would like to add that this site is very useful. I often use questions asked by others to solve my own problems, and I want to take the opportunity to thank.

+4
source share
1 answer

As you wrote in your code, the angle between two (normalized) vectors is the inverse cosine of their point product.

To get the angle under the sign, you can use the third vector representing the normal of the plane on which the other two vectors lie - in your two-dimensional case it will be a three-dimensional vector pointing straight up, for example (0, 0, 1).

Then we take the transverse product of the first vector (the one to which you want to relate the angle) with the second vector (the cross-product note is not commutative). The sign of the angle must be the same as the sign of the point product between the resulting vector and the plane normal.

In the code (C #, sorry) - note that all vectors are considered normalized:

 public static double AngleTo(this Vector3 source, Vector3 dest) { if (source == dest) { return 0; } double dot; Vector3.Dot(ref source, ref dest, out dot); return Math.Acos(dot); } public static double SignedAngleTo(this Vector3 source, Vector3 dest, Vector3 planeNormal) { var angle = source.AngleTo(dest); Vector3 cross; Vector3.Cross(ref source, ref dest, out cross); double dot; Vector3.Dot(ref cross, ref planeNormal, out dot); return dot < 0 ? -angle : angle; } 

This works by taking advantage of the fact that the cross product between two vectors gives a third vector perpendicular (normal) to the plane defined by the first two (therefore, it is essentially a three-dimensional operation). axb = -(bxa) , so the vector will always be perpendicular to the plane, but on the other side depending on the (signed) angle between a and b (there is something called the right rule ).

Thus, the cross product gives us a signed vector perpendicular to the plane, which changes direction when the angle between the vectors passes through 180 °. If we know in advance a vector perpendicular to the plane that is directed upwards, then we can determine whether the transverse product is in the same direction as the plane, normal or not, by checking the sign of their point product.

+9
source

All Articles