This is more of an optimization problem.
I have given a vector u and a list of vectors v. Now I want to sort the list of vectors v so that the vectors with the smallest counterclockwise angle to u come first and the vectors with the largest counterclockwise angle to u come last. That means I would need to have some kind of function that calculates the counterclockwise angle and then I can use it for the comparison. All vectors are given with x and y coordinates, so I only need it in 2D, and they can all be of different length.
Given such a function I could sort my list like this:
Vector u = ...;
std::sort(vectors.begin(), vectors.end(), [&u](const Vector& v1, const Vector& v2)
{
return getAngle(v1, u) < getAngle(v2, u);
}
);
I already know that there is a way to calculate the angle like this using the dot product, determinant and the atan2 function as answered in this question. But what I need is a more efficient way of doing it without using "slow" functions like division, square root or atan2 (slower in comparison to simple addition or multiplication). The good thing is that I don't need to exactly compute the angle, I just want to know which one is larger (for the sorting algorithm). I know there are some ways to optimize out divisions or square roots for comparisons, like in this example:
sqrt(a*a + b*b) < sqrt(c*c + d*d)
a*a + b*b < c*c + d*d //doesn't need a sqrt
And comparing the angles with atan2 could look like this:
atan2(dot(v1, u), det(v1, u)) < atan2(dot(v2, u), det(v2, u))
And now I need a way for doing this without the atan2 function for better efficiency.
And I also already know how to compare the angles efficiently using the acos of the dot product divided by the length of the two vectors multiplied:
acos(dot(v1, u) / (v1.length() * u.length())) < acos(dot(v2, u) / (v2.length() * u.length()))
//remove the acos and flip the comparison operator
dot(v1, u) / (v1.length() * u.length()) > dot(v2, u) / (v2.length() * u.length())
//remove u.length() from both sides
dot(v1, u) / v1.length() > dot(v2, u) / v2.length()
//multiply both sides by v1.length() and v2.length()
dot(v1, u) * v2.length() > dot(v2, u) * v1.length()
//further we could square both sides and use abs on one factor to keep the sign
dot(v1, u) * abs(dot(v1, u)) * v2.lengthSqr() > dot(v2, u) * abs(dot(v2, u)) * v1.lengthSqr()
//now we can compare the two angles without having any division, sqrt or acos function
//I hope this method is correct??
But that doesn't always give me the counterclockwise angle, the angle would always be between 0° and 180°.
So, is there some way to modify one of these two algorithms to make it efficient and work for only counterclockwise angles?