两个二维向量之间的夹角

16

我试图计算两个向量之间的夹角。我尝试了这个方法,但它总是返回零:

public double GetAngle(Vector2 a, Vector2 b)
{
    double angle = Math.Atan2(b.Y, b.X) - Math.Atan2(a.Y, a.X);
    return angle;
}

GetAngle(new Vector2(1,1), new Vector2(50,50));

向量我需要的角度


7
Math.Atan2(b.Y - a.Y,b.X - a.X); 可以翻译为“求点 b 相对于点 a 的方向角度,使用反正切函数 Math.Atan2() 计算,其中参数为 b.Y - a.Y 和 b.X - a.X”。 - Shmiddty
4
如果那是一个答案,你应该将其发布为答案。 - Jon B
这可能会给你从0到斜边的角度。所以,我认为你想要:Math.PI - angle - Shmiddty
回答这个问题可能也有用:http://stackoverflow.com/questions/4159219/angle-measurer-in-c-sharp - RenniePet
1
问题描述有些混淆。你是想要求两个向量之间的夹角还是一个由两个向量组成的直角三角形的角度? - RunHolt
9个回答

30

你应该查看atan2的文档(这里)。

你需要做的是找到B(你的左上向量)与A(你的右下向量)之间的差异,然后将其作为参数传递给atan2函数。

return Math.Atan2(b.Y - a.Y, b.X - a.X);
您当前的代码是找到向量 b 相对于点 0,0 的角度,然后减去向量 a 相对于点 0,0 的角度。

始终得到 0 的原因是因为点 1,1 和 50,50 在通过点 0,0 的同一条直线上(两次调用都返回约为 0.785398 的值),所以将它们相减将导致结果为 0。


2
谢谢,它是以弧度为单位的,所以我会使用MathHelper.ToDegrees((float)angle),当然 :)。 - Sorashi
1
是的,返回值以弧度为单位 :) - emartel
这是否与先减去向量以获得方向向量相同?然后在新向量的X和Y上运行Atan2? - Serguei Fedorov
是的,这完全是一样的!想象一下向量 (0.5, 0.5) 和 (-0.5, 0.5),分别与 X 轴成 45 度和 135 度。如果你将这两个向量相减,你会得到 (1, 0),它与 X 轴成 90 度。 - emartel
2
这是不正确的。这测量了向量a和b的端点之间的夹角。 - RunHolt
显示剩余3条评论

9
我认为下面从.NET源代码中复制的代码可以帮助你。
参考: http://referencesource.microsoft.com/#WindowsBase/Base/System/Windows/Vector.cs,102
/// <summary>
/// AngleBetween - the angle between 2 vectors
/// </summary>
/// <returns>
/// Returns the the angle in degrees between vector1 and vector2
/// </returns>
/// <param name="vector1"> The first Vector </param>
/// <param name="vector2"> The second Vector </param>
public static double AngleBetween(Vector vector1, Vector vector2)
{
    double sin = vector1._x * vector2._y - vector2._x * vector1._y;  
    double cos = vector1._x * vector2._x + vector1._y * vector2._y;

    return Math.Atan2(sin, cos) * (180 / Math.PI);
}

5
一个简单的解决方案应该是这样的:
Vector2 a_normalized = normalize(a);
Vector2 b_normalized = normalize(b);
double angle = arccos(dot(a_normalized,b_normalized));

http://simple.wikipedia.org/wiki/Dot_product

以下是伪代码,因为C#不是我的领域。抱歉。


4

如果你正在寻找“向量a和b之间的夹角”,你需要计算向量a的角度与向量b的角度之间的差值:

Math.Atan2(b.Y, b.X) - Math.Atan2(a.Y, a.X)

但是这个图表与“向量之间的夹角”不匹配。该图表的答案确实是先前给出的答案:
Math.Atan2(b.Y - a.Y, b.X - a.X)

2

我有点晚了,但是关于Vector类的静态方法怎么样:

Vector.AngleBetween(vector1, vector2)

相同的答案已经在这里了,不过感谢您的关注 https://dev59.com/UmYr5IYBdhLWcg3wuMX9#28123501 - Sorashi

2

在Atan2方法中,您必须使用x和y的差异:

Math.Atan2(b.Y - a.Y,b.X - a.X);

此外,我认为这将为您提供从0到所提供三角形的斜边的角度(不完全确定)。

我建议尝试Math.PI - angle


0

tan(angle) = 对边/邻边

arctan(对边/邻边) = angle

对边 = a.y - b.y

邻边 = b.x - a.x

Math.Atan((a.Y - b.Y) / (b.X - a.X));

0
public static class FunAngleCalc
{
    public static double angle(MathPoint p1, MathPoint center, MathPoint p2)
    {
        MathPoint transformedP1 = new MathPoint(p1.x - center.x, p1.y - center.y);

        MathPoint transformedP2 = new MathPoint(p2.x - center.x, p2.y - center.y);
        double angleToP1 = Math.Atan2(transformedP1.y, transformedP1.x);

        double angleToP2 = Math.Atan2(transformedP2.y, transformedP2.x);

        return toDegrees(normaliseToInteriorAngle(angleToP2 - angleToP1));
    }

    private static double normaliseToInteriorAngle(double angle)
    {
        if (angle < 0)
        {
            angle += (2 * Math.PI);
        }
        if (angle > Math.PI)
        {
            angle = 2 * Math.PI - angle;
        }
        return angle;
    }

    private static double toDegrees(double radians)
    {
        return 360 * radians / (2 * Math.PI);
    }
}

0

由于您使用了 Vector2 类,我猜您可以使用

a-b

来获取从 a 到 b 的向量。

因此,您需要的角度是:π - angle(a-b)。


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