locked
Angle between vectors RRS feed

  • Question

  • Hi !

    Can you provide me with asimple code (in C) that calculates the angles between two vectoors provided that the angle ranges from [-pi,pi] ?!

    Two formulas available are :

    A*B=|A|.|B|tan(Teta)

    A.B = |A||B|cos(Teta)

    I think I need to use the first one using atan2() function to have symmetric(+&-) results. Any idea?




    Thursday, August 27, 2009 2:44 PM

Answers


  • I think I need to use the first one using atan2() function to have symmetric(+&-) results. Any idea?


    That is exactly right.  Using A.B = |A||B|cos(t) will provide angles from -pi/2 -> +pi/2.

    This works out (in 2D) as:

    double angle = atan2(vec2.y, vec2.x) - atan2(vec1.y, vec1.x);

    If you want this in 3D, you probably will need to just use the cross product, and compute that axis separately.  Otherwise, I'd recommend going with quaternions.

    Reed Copsey, Jr. - http://reedcopsey.com
    • Marked as answer by yade Thursday, August 27, 2009 3:45 PM
    Thursday, August 27, 2009 3:21 PM
  • I think I need to use the first one using atan2() function to have symmetric(+&-) results. Any idea?
    That is exactly right.  Using A.B = |A||B|cos(t) will provide angles from -pi/2 -> +pi/2.

    I'm not sure. The acos f unction (inverse of cos ) returns the value in range [0, pi], as can be read here:

    http://msdn.microsoft.com/en-us/library/bztkwykh.aspx

    Giovanni


    Giovanni -

    You're absolutely right.  Sorry about that.  using A.B = ... will give you angles between 0 -> pi.

    yade -

    You'll want to use atan2 to get the results you want, as I posted before.  I just misspoke in the first section there.

    Reed Copsey, Jr. - http://reedcopsey.com
    • Marked as answer by yade Thursday, August 27, 2009 3:46 PM
    Thursday, August 27, 2009 3:32 PM

All replies


  • I think I need to use the first one using atan2() function to have symmetric(+&-) results. Any idea?


    That is exactly right.  Using A.B = |A||B|cos(t) will provide angles from -pi/2 -> +pi/2.

    This works out (in 2D) as:

    double angle = atan2(vec2.y, vec2.x) - atan2(vec1.y, vec1.x);

    If you want this in 3D, you probably will need to just use the cross product, and compute that axis separately.  Otherwise, I'd recommend going with quaternions.

    Reed Copsey, Jr. - http://reedcopsey.com
    • Marked as answer by yade Thursday, August 27, 2009 3:45 PM
    Thursday, August 27, 2009 3:21 PM

  • I think I need to use the first one using atan2() function to have symmetric(+&-) results. Any idea?


    That is exactly right.  Using A.B = |A||B|cos(t) will provide angles from -pi/2 -> +pi/2.


    I'm not sure. The acos  function (inverse of cos ) returns the value in range [0, pi], as can be read here:

    http://msdn.microsoft.com/en-us/library/bztkwykh.aspx

    Giovanni


    Thursday, August 27, 2009 3:28 PM
  • I would suggest you to use the dot product formula, which involves the cosine of the angle between the two vectors.
    You can do a little bit of math, and use acos() function (i.e. the inverse of cosine) to get the value of the angle theta, expressing it in terms of dot product between two given vectors and their modules, i.e.:

      theta = acos( a . b / (|a| |b|) )

    where '.' represents the dot product between two vectors.

    Note that the acos() function returns an angle in radians in range [0, pi].

    This is a sample compilable C code I wrote to show that (I did not test it extensively, but it should work):

    #include <stdio.h>
    #include <math.h>
    
    
    // Given 3D vector 'v', returns its module (i.e. length)
    double Vec3_Module(const double * v)
    {
        return sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
    }
    
    // Given two 3D vectors, returns the dot product between them
    double Vec3_Dot(const double * a, const double * b)
    {
        return (a[0]*b[0] + a[1]*b[1] + a[2]*b[2]);
    }
    
    // Given a pair of 3D vectors, returns the angle between them.
    // Angle is expressed in radians, in range [0, PI]
    double Vec3_Angle(const double * a, const double * b)
    {
        //
        // From dot product definition:
        //
        // a . b = |a| |b| cos(theta)
        //
        //  ==>  cos(theta) = a . b / (|a| |b|)
        //
        //  ==>  theta = acos( a . b / (|a| |b|) )
        //
    
        return acos( Vec3_Dot(a, b) / (Vec3_Module(a) * Vec3_Module(b)) );
    }
    
    
    // Test Vec3_Angle function
    void Test()
    {
        double a[] = {1, 2, -1};
        double b[] = {0, 1, -3};
    
        printf("a = [%g, %g, %g]\n", a[0], a[1], a[2]);
        printf("b = [%g, %g, %g]\n", b[0], b[1], b[2]);
        printf("Angle = %g\n", Vec3_Angle(a, b));
    }
    
    
    int main()
    {
        Test();
        return 0;
    }
    


    HTH,
    Giovanni


    Thursday, August 27, 2009 3:32 PM
  • I think I need to use the first one using atan2() function to have symmetric(+&-) results. Any idea?
    That is exactly right.  Using A.B = |A||B|cos(t) will provide angles from -pi/2 -> +pi/2.

    I'm not sure. The acos f unction (inverse of cos ) returns the value in range [0, pi], as can be read here:

    http://msdn.microsoft.com/en-us/library/bztkwykh.aspx

    Giovanni


    Giovanni -

    You're absolutely right.  Sorry about that.  using A.B = ... will give you angles between 0 -> pi.

    yade -

    You'll want to use atan2 to get the results you want, as I posted before.  I just misspoke in the first section there.

    Reed Copsey, Jr. - http://reedcopsey.com
    • Marked as answer by yade Thursday, August 27, 2009 3:46 PM
    Thursday, August 27, 2009 3:32 PM
  • Thanks Guys !

    I think atan2 is the best way to do it. I am gonna check it, let u know if it was not correct !

    Many Thanks!
    Thursday, August 27, 2009 3:46 PM