Reputation: 41402
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
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:
where theta is the angle between the two vectors; thus, inverting the formula, you get:
Upvotes: 3
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
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