Calculate direction angle from two vectors?

后端 未结 4 906
时光说笑
时光说笑 2021-02-03 10:13

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

相关标签:
4条回答
  • 2021-02-03 10:45

    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.

    0 讨论(0)
  • 2021-02-03 10:50

    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.

    0 讨论(0)
  • 2021-02-03 10:55

    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).

    0 讨论(0)
  • 2021-02-03 11:03

    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
     }
    
    0 讨论(0)
提交回复
热议问题