This code is attempting to keep angle
within an interval around zero.
However, managing angles in this way is troublesome and requires considerable care. If it is not accompanied by documentation explaining what is being done, why, and the various errors and specifications that are involved, then it was done improperly.
It is impossible for this sort of angle reduction to keep accumulated changes accurately over a long sequence of changes, because M_PI
is only an approximation to π. Therefore, this sort of reduction is generally only useful for aesthetic or interface effect. E.g., as some angle changes, reducing it can keep it from growing to a point where there may be large jumps in calculation results due to floating-point quantization or other calculation errors that would be annoying to a viewer. Thus, keeping the angle within an interval around zero makes the display look good, even though it diverges from what real physics would do over the long term.
The choice of FLT_EPSILON
appears to be arbitrary. FLT_EPSILON
is important for its representation of the fineness of the float
format. However, at the magnitude of M_PI
, the ULP (finest change) of a float
is actually 2*FLT_EPSILON
. Additionally, JavaScript performs the addition with double-precision arithmetic, and FLT_EPSILON
is of no particular significance in this double
format. I suspect the author simply chose FLT_EPSILON
because it was a convenient “small” number. I expect the code would work just as well as if angle > M_PI
had been written, without the embellishment, and (float) M_PI
were changed to M_PI
everywhere it appears. (The addition of FLT_EPSILON
may have been intended to add some hysteresis to the system, so that it did not frequently toggle between values near π and values near –π. However, the criterion I suggest, angle > M_PI
, also includes some of the same effect, albeit a smaller amount. That might not be apparent to somebody inexperienced with floating-point arithmetic.)
Also, it looks like angle = fmodf(angle, (float) M_PI);
may be a bug, since this is reducing modulo M_PI
rather than 2*M_PI
, so it will add 180º to some angles, producing a completely incorrect result.
It is possible that replacing the entire function body with return fmod(angle, 2*M_PI);
would work satisfactorily.