Question

Say I have two 2D vectors, one for an objects current position and one for that objects previous position. How can I work out the angular direction of travel?

This image might help understand what I'm after:

(image) http://files.me.com/james.ingham/crcvmy

Was it helpful?

Solution

The direction vector of travel will be the difference of the two position vectors,

d = (x1, y1) - (x, y) = (x1 - x, y1 - y)

Now when you ask for the direction angle, that depends what direction you want to measure the angle against. Is it against the x axis? Go with Radu's answer. Against an arbitrary vector? See justjeff's answer.

Edit: To get the angle against the y-axis:

tan (theta) = (x1 -x)/(y1 - y)          

the tangent of the angle is the ratio of the x-coordinate of the difference vector to the y-coordinate of the difference vector.

So

theta = arctan[(x1 - x)/(y1 - y)]

Where arctan means inverse tangent. Not to be confused with the reciprocal of the tangent, which many people do, since they're both frequently denoted tan^-1. And make sure you know whether you're working in degrees or radians.

OTHER TIPS

If you're in C (or other language that uses the same function set) then you're probably looking for the atan2() function. From your diagram:

double theta = atan2(x1-x, y1-y);

That angle will be from the vertical axis, as you marked, and will be measured in radians (God's own angle unit).

Be careful to use atan2 to avoid quadrant issues and division by zero. That's what it's there for.

float getAngle(CGPoint ptA, CGPoint ptOrigin, CGPoint ptB)
{
    CGPoint A = makeVec(ptOrigin, ptA);
    CGPoint B = makeVec(ptOrigin, ptB);

    // angle with +ve x-axis, in the range (−π, π]
    float thetaA = atan2(A.x, A.y);  
    float thetaB = atan2(B.x, B.y);

    float thetaAB = thetaB - thetaA;

    // get in range (−π, π]
    while (thetaAB <= - M_PI)
        thetaAB += 2 * M_PI;

    while (thetaAB > M_PI)
        thetaAB -= 2 * M_PI;

    return thetaAB;
}

However, if you don't care about whether it's a +ve or -ve angle, just use the dot product rule (less CPU load):

float dotProduct(CGPoint p1, CGPoint p2) { return p1.x * p2.x + p1.y * p2.y; }

float getAngle(CGPoint A, CGPoint O, CGPoint B)
{
    CGPoint U = makeVec(O, A);
    CGPoint V = makeVec(O, B);

    float magU = vecGetMag(U);
    float magV = vecGetMag(V);
    float magUmagV = magU * magV;   assert (ABS(magUmagV) > 0.00001);

    // U.V = |U| |V| cos t
    float cosT = dotProduct(U, V) / magUmagV;
    float theta = acos(cosT);
    return theta;
}

Note that in either code section above, if one ( or both ) vectors are close to 0 length this is going to fail. So you might want to trap that somehow.

Still not sure what you mean by rotation matrices, but this is a simple case of getting an azimuth from a direction vector.

The complicated answer:

Normally you should pack a few conversion/utility functions with your 2D vectors: one to convert from X,Y (carthesian) to Theta,R (polar coordinates). You should also support basic vector operations like addition, substraction and dot product. Your answer in this case would be:

 double azimuth  =  (P2 - P1).ToPolarCoordinate().Azimuth;

Where ToPolarCoordinate() and ToCarhtesianCoordinate() are two reciprocal functions switching from one type of vector to another.

The simple one:

 double azimuth = acos ((x2-x1)/sqrt((x2-x1) * (x2-x1) + (y2-y1) * (y2-y1));
 //then do a quadrant resolution based on the +/- sign of (y2-y1) and (x2-x1)
 if (x2-x1)>0 {
   if (y2-y1)<0 {  azimuth = Pi-azimuth; } //quadrant 2
 } else 
 { if (y2-y1)> 0 {  azimuth = 2*Pi-azimuth;} //quadrant 4
    else  { azimuth = Pi + azimuth;} //quadrant 3
 }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top