Search code examples
c++mathvectorradians

c++ - Vector2D math not giving me the right results


I'm trying to create a vector2D class for my game but I think I'm getting the math wrong.

When I create a new vector2d object it automatically sets its x and y to 1, 1 in the constructor.

    Vector2D vec;

    std::cout << " x: " << vec.GetX() << " y: " << vec.GetY() << " angle rad: " << vec.GetAngleRad() << " magnitude: " << vec.GetMagnitude() << std::endl;



    system("pause");
    return 0;

and it outputs:
x: 1
y: 1
angle in rad: 0.785398
magnitude: 1.41421
(which is exactly what i expect)

but the problem is when I parse anything to the setAngle funciton, I get some wired results.

For example:

Vector2D vec;

vec.SetAngleRad(3);

std::cout << " x: " << vec.GetX() << " y: " << vec.GetY() << " angle rad: " << vec.GetAngleRad() << " magnitude: " << vec.GetMagnitude() << std::endl;



system("pause");
return 0;

I would expect it to output angle in rad: 3
but instead I get angle in rad: 0.141593.

This is the vector2D class (I've tried to comment my code so you can see my what I was thinking when I wrote it):

#include "Vector2D.h"



Vector2D::Vector2D():
    _x(1.0f),
    _y(1.0f)
{

}


Vector2D::~Vector2D()
{

}

void Vector2D::SetX(float x)
{
    _x = x;
}

float Vector2D::GetX()
{
    return _x;
}


void Vector2D::SetY(float y)
{
    _y = y;
}

float Vector2D::GetY()
{
    return _y;
}


void Vector2D::SetAngleRad(float angle)
{
    float hypotenuse = GetMagnitude();

    SetX( cos(angle) * hypotenuse); // cos of angle = x / hypotenuse
                                    // so x = cos of angle * hypotenuse

    SetY( sin(angle) * hypotenuse); //sin of angle = y / hypotenuse
                                    // so y = sin of angle * hypotenuse
}

float Vector2D::GetAngleRad()
{
    float hypotenuse = GetMagnitude();
    return asin( _y / hypotenuse ); // if sin of angle A = y / hypotenuse
                                    // then asin of y / hypotenuse = angle
}


void Vector2D::SetMagnitude(float magnitude)
{
    float angle = GetAngleRad();
    float hypotenuse = GetMagnitude();

    SetX( (cos(angle) * hypotenuse) * magnitude ); // cos of angle = x / hypotenuse
                                                   // so cos of angle * hypotenuse = x
                                                   // multiplied by the new magnitude


    SetY( (sin(angle) * hypotenuse) * magnitude); //sin of angle = y / hypotenuse
                                                  // so sin of angle * hypotenuse = y
                                                  // multipied by the new magnitude
}

float Vector2D::GetMagnitude()
{
    return sqrt( (_x * _x) + (_y * _y) ); // a^2 + b^2 = c^2
                                          //so c = sqrt( a^2 + b^2 )
}

So I'd really appreciate it if someone could explain to me what I'm doing wrong here :)


Solution

  • To get angle in full circle range, you have to use both y and x components with atan2 function

    return atan2( _y, _x );
    

    Note result range -Pi..Pi and correct negative one by +2*Pi if you need range 0..2*Pi

    Another issue: :SetMagnitude method really multiplies current magnitude by magnitude multiplier, while name assumes that method should set it (so vector length 2 after applying SetMagnitude(2) will have magnitude 4)).

    So it would better to remove *hypotenuse multiplication (or change method name)