Search code examples
mathtrigonometrydivide-by-zero

How should I tackle ARCTAN (and prevent deviding by zero) without the convenience of ARCTAN2(n,m) being available?


I try to determine the angle from a point (n,m) to (0,0). Without arctan2 being available, I'm running into the problem that m can be 0, which leads to a possible division by zero.

What would be an elegant, correct solution to tackling this issue?


Solution

  • don't use the conventional quadrants, use the branch points defined by the lines y = +/- x, and use the 1st two steps of a CORDIC-like algorithm (e.g. rotate coordinates by a known angle and keep track of how much you've rotated):

    function atan2_substitute(x,y)
    {
       double angle = 0;
       if (x < y)
       { angle = M_PI; x = -x; y = -y; }
       // this guarantees that the angle is between -135 and +45 degrees
    
       if (x < -y)
       {
         angle -= M_PI/2; tmp = x; x = -y; y = tmp;
       }
       // this guarantees that the angle is between -45 and +45
    
       angle += atan(y/x);
    
       if (angle > M_PI)
          angle -= 2*M_PI;
       // fails at 0,0; otherwise is accurate over the entire plane
    }
    

    the reason for doing it this way is that atan() may be more likely to be accurate for ratios y/x between -1 and +1, than for ratios greater than 1. (though a good atan() algorithm would recognize this and take the reciprocal)