如何从垂直方向计算矢量的角度?

时间:2010-08-09 15:51:54

标签: algorithm language-agnostic math trigonometry

我试图找出两个2D矢量之间的角度(以度为单位)。我知道我需要使用trig,但我对它不太好。这就是我想要解决的问题(Y轴向下增加): alt text http://i38.tinypic.com/2dcefch.png

我正在尝试使用此代码,但它根本不起作用(由于某种原因计算随机角度):

private float calcAngle(float x, float y, float x1, float y1)
{
    float _angle = (float)Math.toDegrees(Math.atan2(Math.abs(x1-x), Math.abs(y1-y)));
    Log.d("Angle","Angle: "+_angle+" x: "+x+" y: "+y+" x1: "+x1+" y1: "+y1);
    return _angle;
}

这些是我的结果(提供恒定位置时常数,但当我改变位置时,角度改变,我找不到两个角度之间的任何联系):

位置1: x:100 y:100 x1:50 y1:50 角度:45

职位2: x:92 y:85 x1:24 y1:16 角度:44.58

职位3: x:44 y:16 x1:106 y1:132 角度:28.12

编辑:谢谢所有回答并帮助我弄清楚错误的人!对不起,标题和问题令人困惑。

9 个答案:

答案 0 :(得分:14)

首先必须了解如何计算两个向量之间的角度,其中有几个。我会告诉你我认为最简单的事情。

  1. 鉴于 v1 v2 ,其点积为:v1x * v2x + v1y * v2y
  2. 向量 v 的范数由下式给出:sqtr(vx ^ 2 + vy ^ 2)
  3. 有了这些信息,请采用以下定义:

    dot(v1, v2) = norm(v1) * norm(v2) * cos(angle(v1, v2))
    

    现在,您解决​​angle(v1, v2)

    angle(v1, v2) = acos( dot(v1, v2) / (norm(v1) * norm(v2)) )
    

    最后,根据开头给出的定义,最后得到:

    angle(v1, v2) = acos( (v1x * v2x + v1y * v2y) / (sqrt(v1x^2+v1y^2) * sqrt(v2x^2+v2y^2)) )
    

    同样,有很多方法可以做到这一点,但我喜欢这个,因为它给出了给定矢量给定角度和范数或角度的点积。

    答案是弧度,但你知道pi弧度(即3.14弧度)是180度,所以你只需乘以转换因子180 / pi。

答案 1 :(得分:13)

啊哈!结果我只需要翻转我的角度并使用atan2。这是我的最终代码:

private float calcAngle(float x, float y, float x1, float y1)
{
    float _angle = (float)Math.toDegrees(Math.atan2(x1-x, y-y1));
    return _angle;
}

感谢大家帮助我解决这个问题,并帮助我理解我在做什么! :)

答案 2 :(得分:5)

不要将参数的绝对值设为atan2atan2的全部意义在于它使用其参数的符号来确定角度所在的qaudrant。通过取绝对值,您强制atan2仅返回0到pi之间的值/ 2而不是-pi到pi。

答案 3 :(得分:2)

看起来Niall想出来了,但无论如何我会完成我的解释。除了解释解决方案的工作原理外,我的解决方案还有两个优点:

  • 避免atan2()内的零除零
  • 返回值在0到360度范围内始终为正

atan2()返回相对于正X轴的逆时针角度。 Niall正在寻找相对于正Y轴的顺时针角度(在由两个点和正Y轴形成的矢量之间)。

以下功能改编自我的小行星游戏,我想计算船舶/速度矢量的方向“指向:”

// Calculate angle between vector from (x1,y1) to (x2,y2) & +Y axis in degrees.
// Essentially gives a compass reading, where N is 0 degrees and E is 90 degrees.

double bearing(double x1, double y1, double x2, double y2)
{
    // x and y args to atan2() swapped to rotate resulting angle 90 degrees
    // (Thus angle in respect to +Y axis instead of +X axis)
    double angle = Math.toDegrees(atan2(x1 - x2, y2 - y1));

    // Ensure result is in interval [0, 360)
    // Subtract because positive degree angles go clockwise
    return (360 - angle) %  360;
}

答案 4 :(得分:1)

我相信两个向量之间角度的等式应该更像:

toDegrees(acos((x*x1+y*y1)/(sqrt(x*x+y*y)*sqrt(x1*x1+y1*y1))))

上面的等式将计算矢量p1-p2与通过从点p2到矢量p1的正交延伸而产生的线之间的角度。

两个矢量V1和V2的点积等于| V1 | * | V2 | cos(θ)。因此,θ等于acos((V1点V2)/(| V1 | | V2 |))。 V1点V2是V1.x V2.x + V1.y V2.y。 V的大小(即| V |)是pathogorean定理... sqrt(V.x ^ 2 + V.y ^ 2)

答案 5 :(得分:0)

应该是:

atan( abs(x1 - x)/abs(y1 - y) ) 

abs代表绝对值(避免负值)

答案 6 :(得分:0)

你正在使用整数吗?将参数转换为双精度,我会在结果上使用fab,而不是参数。结果将是弧度;要获得学位,请使用:

res * =(360.0 /(2.0 * Math.PI));

答案 7 :(得分:0)

我的第一个猜测是使用atan(y / x)计算每个矢量与轴的角度,然后减去那些天使并取绝对值,即:

abs(atan(y / x) - atan(y1 / x1))

答案 8 :(得分:0)

第二个向量相对于第一个= atan2(y2,x2) - atan2(y1,x1)的角度。

http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/index.htm