将角度转换为向量

15

我正在进行游戏编程。FWIW 我正在使用XNA,但我怀疑这并不相关。

我想将角度转换为方向向量(即X和Y),其大小为1。

我的原点(0,0)位于左上角。

所以我希望0度转换为[0,-1]

我认为最好的方法是使用矩阵旋转我的North/Up的定义,但似乎这并不起作用。

以下是代码...

public class Conversion
{
    public static Vector2 GetDirectionVectorFromDegrees(float Degrees)
    {
        Vector2 North= new Vector2(0, -1);
        float Radians = MathHelper.ToRadians(Degrees);

        var RotationMatrix = Matrix.CreateRotationZ(Radians);
        return Vector2.Transform(North, RotationMatrix);
    }
}

......这里是我的单元测试代码......

[TestFixture]
public class Turning_Tests
{
    [Test]
    public void Degrees0_Tests()
    {
        Vector2 result = Conversion.GetDirectionVectorFromDegrees(0);
        Assert.AreEqual(0, result.X);
        Assert.AreEqual(-1, result.Y);
    }
    [Test]
    public void Degrees90_Tests()
    {
        Vector2 result = Conversion.GetDirectionVectorFromDegrees(90);
        Assert.AreEqual(1, result.X);
        Assert.AreEqual(0, result.Y);
    }
    [Test]
    public void Degrees180_Tests()
    {
        Vector2 result = Conversion.GetDirectionVectorFromDegrees(180);
        Assert.AreEqual(0, result.X);
        Assert.AreEqual(1, result.Y);
    }
    [Test]
    public void Degrees270_Tests()
    {
        Vector2 result = Conversion.GetDirectionVectorFromDegrees(270);
        Assert.AreEqual(-1, result.X);
        Assert.AreEqual(0, result.Y);
    }

}

我是否以错误的方式开始? 我应该使用矩阵吗? 我是不是在错误的位置将度数转换为弧度?

我看到有人建议可以使用以下代码来完成此操作:

new Vector2((float)Math.Cos(Angle), (float)Math.Sin(Angle));

...有时候...

new Vector2((float)Math.Sin(Angle), (float)Math.Cos(Angle));

不过这些似乎也不起作用。

有人能帮我找到正确的方法...或者最好是给我一些代码,使得这4个提供的单元测试都通过吗?

非常感谢您的帮助。

1个回答

24

只需使用:

new Vector2((float)Math.Cos(radians), (float)Math.Sin(radians))

请确保使用此方法时将角度转换为弧度。

这使用数学家的约定,从[1,0]开始,并沿着指向[0,1]的方向前进(即按照数学家用于两个轴的方向逆时针方向)。

如果您要改为使用自己的约定(从[0,-1]开始,并沿着指向[1,0]的方向前进),您需要:

new Vector2((float)Math.Sin(radians), -(float)Math.Cos(radians))

请注意,将角度转换为弧度永远不可能是精确的(它涉及到 π 的某些内容)。在您的测试中应允许一定的误差。此外,如果您将 radians 使用double 而不是 float,则在中间计算中会获得一些额外的精度。


@RoryBecker 请看我的编辑。在使用“Sin”和“Cos”时,您不能期望得到精确值。不过这些值必须非常接近预期值。 - Jeppe Stig Nielsen
当我看到我的单元测试失败时,我认为这很糟糕。然而正如你所指出的那样,这是由于舍入误差造成的,而这些误差实际上在可接受的范围内。非常感谢 :) - Rory Becker
实际上,有八种不同的可能性来确定从哪个“角落”(轴与单位圆之间的交点)开始(4种可能性),以及使用哪个方向(顺时针或逆时针)(2种可能性)。这对应于选择 CosSin 的顺序(即先是 Cos(x),然后是 Sin(y),或者反之)的八种可能性,第一个坐标上的符号(减号或不带符号),以及最后一个坐标上的符号。 - Jeppe Stig Nielsen
顺带一提,我已经升级了我的 NUnit 版本,现在调用新的 AreEqual 重载函数,可以使用公差参数。在这种情况下,我允许公差为 0.00001。这似乎已经足够了。再次感谢 @Jeppe 的帮助 :) - Rory Becker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接