简体   繁体   中英

Find “middle / average” angle in vector terms

I'm trying to find the average vector given two vectors. When I say "average", I do not mean the basic average where I add the 2 vectors and divide by two - but rather, a directional average. For example:

V1 = {1, 0}
V2 = {-1, 0}
AverageVector = {0, 1} or {0, -1} 

I suppose what I'm looking for is more in the realm of angles. If angle1 = 0, and angle2 = 180, then the average angle is 90, perpendicular to both. If angle1 = 90 and angle2 = 110, then the average angle is 100, etc.

It's important that the solution to find the "average" vector does not use vector to angle conversions (like atan2, sin, cos). I'm looking for a way to find the "average" vector using vector math alone.

Note: all vectors are 2D.

Note on vote to close: The question which as linked as "already answered" does not answer this question. As stated, I must accomplish this without converting the vectors to angles using sin, cos or atan2. The linked question only refers to solutions using such conversions.

Given v0 = (x0, y0) and v1 = (x1, y1), you are looking for v = (x, y) such that the angle between v0 and v is equal to the angle between v and v1. As you correctly observe, there will always be two solutions.

We know that the dot product of two vectors is equal to the product of their magnitudes and the angle separating them - ie, we know that v0 . v = x.x0 + y.y0 = |v||v0|cos(z) and v1 . v = x.x1 + y.y1 = |v||v1|cos(z). Note that the angle, z, remains the same; and we might as well take a unit vector for v, so |v| = 1. Now, we get two equations:

x.x0 + y.y0 = |v0|cos(z)
x.x1 + y.y1 = |v1|cos(z)

We can solve the first for cos(z) and substitute in the second:

x.x1 + y.y1 = (|v1|/|v0|)(x.x0 + y.y0)

Remember, we can take a unit vector for v, so we know that x*x + y*y = 1. Solve the above equation for x in terms of y (or y in terms of x), plug it into x*x + y*y = 1, and then solve for your variable using the quadratic equation. Note: the quadratic equation yields zero, one or two solutions - but you should always fall into the two solution case.

Notice: our solution requires knowledge of vector/angle relationships, but the program need not ever perform any conversions. While we use cos(z) in deriving the mathematics for our program, we end up with an expression that relies only on the vectors' components.

UPDATE based on comments

To figure out which vector is "closest" to the original two, it's useful to notice the following: the two vectors you get from the above expression will be pointing in opposite directions. In other words, there will be 180 degrees separating them.

So, suppose we found "average" vectors A and B for original vectors X and Y. Which of A or B is "closer" to X and Y? Well, we know that

Ax * Xx + Ay * Xy = |A||X|cos(Az)
Bx * Xx + By * Xy = |B||X|cos(Bz)

Now, cosine is largest when the angle is 0, and gets bigger when the angle increases (in absolute value). Since we want the angle closer to 0, we want the larger cosine. Solve each of the above equations for cos(Az) and cos(Bz), respectively; evaluate (all other quantities are known) and then you know the vector whose cosine is largest is "closest" to vector X (hence also to vector Y. Exercise - why must this be true?)

Of course, if cos(Az) = cos(Bz), then A and B are "equidistant" from vector X (and also from Y) - in such cases, X and Y will be parallel, A and B will be parallel, and A/B will be parallel to X/Y.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM