Olical
Olical

Reputation: 41402

Calculating the bearing between two vectors then diff that against a passed angle

I am trying to find the 2D vector in a set that is closest to the provided angle from another vector.

So if I have v(10, 10) and I would like to find the closest other vector along an angle of 90 degrees it should find v(20, 10), for example. I have written a method that I think returns the correct bearing between two vectors.

float getBearing(
    const sf::Vector2f& a, const sf::Vector2f& b)
{
    float degs = atan2f(b.y - a.y, b.x - a.x) * (180 / M_PI);
    return (degs > 0.0f ? degs : (360.0f + degs)) + 90.0f;
}

This seems to work okay although if I place one above another it returns 180, which is fine, and 360, which is just odd. Shouldn't it return 0 if it is directly above it? The best way to do that would be to check for 360 and return 0 I guess.

My problem is that I can't work out the difference between the passed angle, 90 degrees for example, and the one returned from getBearing. I'm not even sure if the returned bearing is correct in all situations.

Can anyone help correct any glaringly obvious mistakes in my bearing method and suggest a way to get the difference between two bearings? I have been hunting through the internet but there are so many ways to do it, most of which are shown in other languages.

Thanks.

Upvotes: 0

Views: 2783

Answers (3)

Matteo Italia
Matteo Italia

Reputation: 126887

If what you need is just to find the vectors nearest to a certain angle, you can follow @swtdrgn method; if, instead, you actually need to compute the angle difference between two vectors, you can exploit a simple property of the dot product:

dot product geometric definition

where theta is the angle between the two vectors; thus, inverting the formula, you get:

inverse of the formula above

Upvotes: 3

Olical
Olical

Reputation: 41402

I have found a solution for now. I have spent a good few hours trying to solve this and I finally do it minutes after asking SO, typical. There may be a much better way of doing this, so I am still open to suggestions from other answers.

I am still using my bearing method from the question at the moment, which will always return a value between 0 and 360. I then get the difference between the returned value and a specified angle like so.

fabs(fmodf(getBearing(vectorA, vectorB) + 180 - angle, 360) - 180);

This will return a positive float that measures the distance in degrees between the bearing between two vectors. @swtdrgn's answer suggests using the dot product of the two vectors, this may be much simpler than my bearing method because I don't actually need the angle, I just need the difference.

Upvotes: 0

swtdrgn
swtdrgn

Reputation: 1184

I would suggest to take the two vectors that are being compared and do an unit dot product. The closest bearing should be greatest, 1 being the maximum (meaning the vectors are pointing to the same direction) and -1 being the minimum (meaning the vectors are pointing to opposite directions).

Upvotes: 2

Related Questions