Search code examples
c#rotation2dvectormath

Rotating 2-vectors, moving backwards and skipping regions. C#


I am trying to use rotations of 2-vectors, but I have run into two problems. Firstly the vectors seems to be rotating backwards, and secondly, the vectors skip between two regions when they rotate.

this is the code I am using for the rotation (in a vector class, with a double x and double y):

public double radians()
{
    return Math.Atan2(y, x);
}

public double len()
{
    return Math.Sqrt(Math.Pow(x, 2) + Math.Pow(y, 2));
}

public vector mul(double d)
{
    return new vector(x * d, y * d);
}

public vector div(double d)
{
    return new vector(x / d, y / d);
}

public vector unit()
{
    return div(len());
}

public vector rotate(vector v)
{
    double theta = v.radians();

    return new vector(
        x * Math.Cos(theta) - y * Math.Sin(theta),
        x * Math.Cos(theta) + y * Math.Sin(theta))
        .unit().mul(len()); // without this, the rotated vector is smaller than the original
}

When I use these to rotate a vector, it rotates counter-clockwise, rather than the clockwise I think it should. To demonstrate, an image:

original vector in gold, rotated in blue

It also rotated by a lot more than I think it should. Another issue that is more difficult to explain is that the rotation works smoothly over about two quarters of it's span, but skips over the other two. Another issue I have found is that if the angle I rotate the vector by is small (in my testing, anything past (1, 10)), the rotation starts strong, but slows and eventually just stops. This looks to me like a precision issue with C#'s double, but I tried to fix it by making sure the length of the rotated vector does not change.

Anyway if you can spot a cause of one or all of my problems, that would be much appreciated.


Solution

  • I solved my problems by changing the functions radians() and rotate(). The other functions were fine.

    radians() fixed:

    public double radians()
    {
        return Math.Atan2(x, y); // swap the x and y
    }
    

    rotate() fixed:

    public vector rotate(vector v)
    {
        double theta = v.radians();
    
        // use the clockwise rotation matrix:
        // |  cos(theta) sin(theta) |
        // | -sin(theta) cos(theta) |
        return new vector(
            x * Math.Cos(theta) + y * Math.Sin(theta),
            x * -Math.Sin(theta) + y * Math.Cos(theta));
    }
    

    this fixed the skipping, backwards rotation, length shortening, and stopping.

    Hope this helps someone like me.