How to calculate the angle of a vector from the vertical?

拈花ヽ惹草 提交于 2019-11-28 23:42:53
Escualo

You first have to understand how to compute angle between two vectors and there are several of them. I will give you what I think is the simplest.

  1. Given v1 and v2, their dot product is: v1x * v2x + v1y * v2y
  2. The norm of a vector v is given by: sqtr(vx^2+vy^2)

With this information, please take this definition:

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

Now, you solve for angle(v1, v2):

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

Finally, taking the definitions given at the beginning, then you end up with:

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

Again, there are many ways to do this, but I like this one because it is helpful for dot product given angle and norm, or angle, given vectors.

The answer will be in radians, but you know that pi radians (that is 3.14 radians) are 180 degrees, so you simply multiply by the conversion factor 180/pi.

Aha! Turns out I just needed to flip my angle and use atan2. This is my final code:

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

Thanks everyone for helping me figure this out and also for helping me to understand what I'm actually doing! :)

Do not take the absolute value of the arguments to atan2. The whole point of atan2 is that it uses the signs of its arguments to work out which qaudrant the angle is in. By taking the absolute values you are forcing atan2 to only return values between 0 and pi/2 instead of -pi to pi.

It looks like Niall figured it out, but I'll finish my explanation, anyways. In addition to explaining why the solution works, my solution has two advantages:

  • Potential division by zero within atan2() is avoided
  • Return value is always positive in the range 0 to 360 degrees

atan2() returns the counter-clockwise angle relative to the positive X axis. Niall was looking for the clockwise angle relative to the positive Y axis (between the vector formed by the two points and the positve Y axis).

The following function is adapted from my asteroids game where I wanted to calculate the direction a ship/velocity vector was "pointing:"

// 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;
}

I believe the equation for the angle between two vectors should look more like:

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

Your above equation will calculate the angle made between the vector p1-p2 and the line made by extending an orthogonal from the point p2 to the vector p1.

The dot product of two vectors V1 and V2 is equal to |V1|*|V2|cos(theta). Therefore, theta is equal to acos((V1 dot V2)/(|V1||V2|)). V1 dot V2 is V1.xV2.x+V1.yV2.y. The magnitude of V (i.e., |V|) is the pathogorean theorem... sqrt(V.x^2 + V.y^2)

It should be :

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

abs stands for absolute (to avoid negative values)

My first guess would be to calculate the angle of each vector with the axes using atan(y/x) and then subtract those angels and take the absolute value, that is:

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

Are you using integers? Cast the arguments as doubles, and I would use fabs on the result, not the arguments. The result will be in radians; to get degrees, use:

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

The angle of the second vector relative to the first = atan2(y2,x2) - atan2(y1,x1).

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!