Arjen Markus (29 january 2004) A programmer's life can be full of surprises: this one has to do with angles and directions. More in particular: how do you determine the angle of a vector (or arrow if you like), if you have its two cartesian components?
If you are a mathematician, you might say, well, that is easy:
angle = atan2(y,x)
with x and y the cartesian components of the vector. That measures the angle of the vector with the positive x-axis in counter-clockwise direction.
If you are involved in navigation or oceanography, you will probably want to know the direction of the vector with respect to the North. Then the angle is measured in clockwise direction from the North:
angle = pi/2 - atan2(y,x) = atan2(x,y)
Hm, unless the vector represents the wind ...
The wind is always expressed as coming from some direction and a ship is going in some direction. Or does it matter?
In either case, you can use the wonderful function atan2() which takes care of the problem: it returns an angle between -pi and pi rad (= -/+180 degrees) and takes care of the right quadrant by considering the sign of the two components.
So, atan2() is more than just atan(y/x)! In fact, if we imagine a typical implementation, we can imagine that that would be optimised for some common cases:
x = 0: atan2(y,x) = pi/2 or -pi/2 y = 0: atan2(y,x) = 0 or pi x = y: atan2(y,x) = pi/4 or -3pi/4 x =-y: atan2(y,x) = 3pi/4 or -pi/4
End of story? No, there is a singular point (x,y) = (0,0), well actually the whole half-line y = 0, x <=0, is singular, as with y just positive, the result of atan2(x,y) is pi and with y just negative, it is -pi.
But for (x,y) = (0,0), the situation is definitely the worst: at this point the function can not be assigned a single valid value (or any value you like, including throwing an error).
I had to deal with a change in a program that, among a lot of other things, has to calculate such angles from the x- and y-components of flow velocity vectors. It turned out that the old implementation of a routine yielded pi/4 for this situation and I bluntly assumed that 0 would be a nice value (a value many numerical libraries will indeed return, though others will throw an error).
If you look at the common cases above, you can see how that might happen:
Depending on the order of checking -- and the precise details! -- anything might result.
I solved this problem, after even considering returning an "undefined" value, after some discussion, to simply set the angle to pi/4.
Another amusing anecdote about angles
In the Tcl chatroom we toyed with the idea to determine the barycentre of all Tclers around the world and turn that into the location of a world-wide Tclers' meeting. Roughly speaking:
meeting coordinates = Sum of the coordinates of Tclers / Number of Tclers
I will spare you the details (at some point in time, someone mentioned that the weight should not be the geographical distance, but the ticket for a flight to the barycentre. That did sound fair, but unfortunately ticket prices are a pathological function of the positions of destination and departure, the airline company and the phase of the moon), but it is actually impossible to come up with a sensible definition of such a barycentre:
Take the following situation:
Three Tclers are located on the equator with an angular distance of 120 degrees
Question: Where should they meet? At one of the poles?
Given various arrangements the barycentre might look either reasonable or absolutely ridiculous.
To make it worse: suppose our beloved planet would have been an infinite cylinder, rather than a rough sphere. We can still imagine an imaginary line called the equator and we can still position our Tclers at equal distances along that equator. But this time there is no pole nearby to meet!