locked
C# Convert magnitude and direction to a vector RRS feed

  • Question

  • I have the following algorithm to create a vector from a magnitude and direction (in degrees). For the direction North is 0 degrees, East is 90 degrees etc etc.

           public static Tuple<double, double> MagnitudeAndDirectionToVector(double speed, double direction)
            {
                double vectorXMultiplier = 1.0;
                double vectorYMultiplier = 1.0;
    
                if (direction == 0.0)
                {
                    return new Tuple<double, double>(0, speed);
                }
                else
                {
                    if ((direction > 0) && (direction <= 90))
                    {
                        direction = 90 - direction;
                    }
                    else if ((direction > 90) && (direction <= 180))
                    {
                        direction = direction - 90; 
                        vectorYMultiplier = -1.0;
                    }
                    else if ((direction > 180) && (direction <= 270))
                    {
                        direction = 270 - direction; vectorYMultiplier = -1.0; 
                        vectorXMultiplier = -1.0;
                    }
                    else if ((direction > 270) && (direction <= 360))
                    {
                        direction = direction - 270; 
                        vectorXMultiplier = -1.0;
                    }
    
                    return new Tuple<double, double>(Math.Cos(direction * DegressToRadians) * speed * vectorXMultiplier, Math.Sin(direction * DegressToRadians) * speed * vectorYMultiplier);
                }

    I don't like the fact that I have case statements and that I have to modify the direction to get the correct vector out. I have a test harness which runs through various scenarios and this code does work but I am sure that there must be a better way. 

    Does anyone know of a better way of doing this?

    Thanks

    Ian

    Tuesday, March 15, 2016 10:09 AM

Answers

  • Thanks for the quick response.

    If you call

    CartesianToPolar_Degrees(1, 2, out angle, out magnitude);

    The angle returned is around 63 degrees. What I actually want is the bearing from 0 i.e. around 26 degrees.

    Any ideas on how to do this?

    Thanks

    Ian


    Natural orientation usually starts at x and curls towards y.

    Choose any direction.  Call that "forward", or "the principal direction" or the "first direction".  In mathematics that first axis is called the Major axis, and the first letter we start handing out for such axes is "x".

    Then choose a direction that is 90 degrees, perpendicular the first direction.  You have lots of choices,  Even working in a flat plane, you have two choices, you can go 90 degrees to the left or to the right.  Whatever you decide, you call that second direction the "minor" axis, and give it the next letter, "y".  A rotation starting at x heading toward y is a positive rotation.  An vector in the direction of x is 0 degrees.  A vector in the direction of y is +90 degrees.  These are the natural definitions for orientation and measurement of angles.

    There are, of course, other ways.  You could define forward to be in the negative y direction, as it may seem natural to do on a computer graphics display where 0 is the top and positive numbers head down your screen toward your feet.  But "right" may still be in the positive x direction, and that may feel like a "positive" rotation to you because that's the way a clock runs.  It's all up to you.  You can invert (use the negative of) of x and/or y as necessary, and you can even swap x and y to achieve a 90 degree rotation.  Do whatever is necessary to get the angles you like.

    But the natural definitions (the ones I used) imply:

    x y angle
    1 0 0
    0 1 +90
    -1 0 +180
    0 -1 -90

    So a vector of (1,2)  means it's more towards y than x, so it's greater than 45 degrees but less than 90.  If you don't like that, change it.

    If you don't like the fact that negative numbers come out of Atan2, then you fix that up after the fact too.

    if( angle < 0.0 ) angle += 360.0;


    • Edited by Wyck Tuesday, March 15, 2016 5:06 PM oops. missed a word or two.
    • Proposed as answer by Kristin Xie Thursday, March 24, 2016 7:54 AM
    • Marked as answer by DotNet Wang Friday, March 25, 2016 12:56 AM
    Tuesday, March 15, 2016 5:05 PM

All replies

  • Just take the sin and cos of the angle.  They're periodic functions.  No need to fix up which quadrant your vector is in.

    And by the way, if you ever need to convert in the opposite direction, that's what Math.Atan2 does.

    What you are doing at the mathematical level, is converting bteween Cartesian coordinates and polar coordinates.  In case you'd like to search the web for such things.

    Here are the two functions:

    void CartesianToPolar_Degrees( double x, double y, out double angle, out double magnitude )
    {
        angle = Math.Atan2( y, x ) * 180.0 / Math.PI;
        magnitude = Math.Sqrt( x * x + y * y );
    
    }
    
    void PolarToCartesian_Degrees( double angle, double magnitude, out double x, out double y )
    {
        double radians = angle * Math.PI / 180.0;
        x = Math.Cos( radians ) * magnitude;
        y = Math.Sin( radians ) * magnitude;
    }
    


    Tuesday, March 15, 2016 2:54 PM
  • Thanks for the quick response.

    If you call

    CartesianToPolar_Degrees(1, 2, out angle, out magnitude);

    The angle returned is around 63 degrees. What I actually want is the bearing from 0 i.e. around 26 degrees.

    Any ideas on how to do this?

    Thanks

    Ian


    Tuesday, March 15, 2016 4:05 PM
  • This seems to work but is it valid?

     
            private void CartesianToPolar_Degrees(double x, double y, out double angle, out double magnitude)
            {
                angle = Math.Atan2(x, y) * 180.0 / Math.PI;
                if (angle < 0) angle += 360;
                magnitude = Math.Sqrt(x * x + y * y);
            }
    
            private void PolarToCartesian_Degrees(double angle, double magnitude, out double x, out double y)
            {
                double radians = angle * Math.PI / 180.0;
                x = Math.Sin(radians) * magnitude;
                y = Math.Cos(radians) * magnitude;
            }
    

    Thanks

    Ian

    Tuesday, March 15, 2016 4:41 PM
  • Thanks for the quick response.

    If you call

    CartesianToPolar_Degrees(1, 2, out angle, out magnitude);

    The angle returned is around 63 degrees. What I actually want is the bearing from 0 i.e. around 26 degrees.

    Any ideas on how to do this?

    Thanks

    Ian


    Natural orientation usually starts at x and curls towards y.

    Choose any direction.  Call that "forward", or "the principal direction" or the "first direction".  In mathematics that first axis is called the Major axis, and the first letter we start handing out for such axes is "x".

    Then choose a direction that is 90 degrees, perpendicular the first direction.  You have lots of choices,  Even working in a flat plane, you have two choices, you can go 90 degrees to the left or to the right.  Whatever you decide, you call that second direction the "minor" axis, and give it the next letter, "y".  A rotation starting at x heading toward y is a positive rotation.  An vector in the direction of x is 0 degrees.  A vector in the direction of y is +90 degrees.  These are the natural definitions for orientation and measurement of angles.

    There are, of course, other ways.  You could define forward to be in the negative y direction, as it may seem natural to do on a computer graphics display where 0 is the top and positive numbers head down your screen toward your feet.  But "right" may still be in the positive x direction, and that may feel like a "positive" rotation to you because that's the way a clock runs.  It's all up to you.  You can invert (use the negative of) of x and/or y as necessary, and you can even swap x and y to achieve a 90 degree rotation.  Do whatever is necessary to get the angles you like.

    But the natural definitions (the ones I used) imply:

    x y angle
    1 0 0
    0 1 +90
    -1 0 +180
    0 -1 -90

    So a vector of (1,2)  means it's more towards y than x, so it's greater than 45 degrees but less than 90.  If you don't like that, change it.

    If you don't like the fact that negative numbers come out of Atan2, then you fix that up after the fact too.

    if( angle < 0.0 ) angle += 360.0;


    • Edited by Wyck Tuesday, March 15, 2016 5:06 PM oops. missed a word or two.
    • Proposed as answer by Kristin Xie Thursday, March 24, 2016 7:54 AM
    • Marked as answer by DotNet Wang Friday, March 25, 2016 12:56 AM
    Tuesday, March 15, 2016 5:05 PM