7

Normally, polar coordinates go from 0 to π to 2π (just before 2π really, as it equals 0 again). However, when using the JavaScript atan2() function, I'm getting a different, weird range:

Cartesian X | Cartesian Y | Theta (θ)
===========================================================
     1      |      0      | 0 (0 × π)
     1      |      1      | 0.7853981633974483 (0.25 × π)
     0      |      1      | 1.5707963267948966 (0.5 × π)
    -1      |      1      | 2.356194490192345 (0.75 × π)
    -1      |      0      | 3.141592653589793 (1 × π)
    -1      |     -1      | -2.356194490192345 (-0.75 × π)
     0      |     -1      | -1.5707963267948966 (-0.5 × π)
     1      |     -1      | -0.7853981633974483 (-0.25 × π)

As you can see, after it reaches π (180°), it jumps down to –π (–180°), and proceeds back up to 0. How can I get it to use the range {0, ..., 2π} instead of {–π, ..., π}? I've been trying to think of every calculation to "fix" the values, but I would also like to know why JavaScript chooses this range instead of the typical polar range. Thanks!

TerranRich
  • 1,251
  • 2
  • 19
  • 35

4 Answers4

8

It's pretty standard for atan2 to return angles in that range; for instance, that's what the atan2 in the C standard library does.

If you want 0..2pi instead of -pi..pi, test whether the result is negative and add 2pi if it is.

Gareth McCaughan
  • 19,045
  • 1
  • 37
  • 55
  • I'm marking this answer as correct only because it answered my question as to "why" (it's standard). I guess I'll just have to deal with that idiosyncrasy. Thanks! – TerranRich Apr 27 '12 at 01:21
  • 1
    You're welcome. There's really nothing any more idiosyncratic about using the range -pi..pi than there would be about 0..2pi. In fact, arguably it makes more sense, because it puts the discontinuity along the negative x-axis rather than the positive x-axis, which is often sensible. For instance, atan2(y,x) is more or less the same thing as the imaginary part of log(x+iy), and you really want that to be defined (and continuous) when x+iy is positive and real. – Gareth McCaughan Apr 27 '12 at 01:24
7

It's atan2(y, x) not atan2(x, y)

gatzkerob
  • 848
  • 2
  • 11
  • 29
  • 2
    Oh god...Took me an hour to resolve my error...Thank you! Why would anyone create an API like that? Is there any reason for this order? – Jan Peter Dec 30 '16 at 14:30
4

If the result is negative just add 2 * PI to the result.

function atan2Normalized(x,y) {
    var result = Math.atan2(x, y);
    if (result < 0) {
        result += (2 * Math.PI);
    }
    return(result);
}
jfriend00
  • 580,699
  • 78
  • 809
  • 825
  • @GarethMcCaughanq - you're right - I knew that, but just typed it wrong. I've corrected it. – jfriend00 Apr 27 '12 at 01:11
  • Thank you! This will definitely help. I could also use a conditional (or whatever the technical term is), like `theta_fixed = (theta > 0) ? theta : (theta + 2 * Math.PI);` – TerranRich Apr 27 '12 at 01:22
0

How can I get it to use the range {0, ..., 2π} instead of {–π, ..., π}?

The Math.atan2(Y,X) function will give different results for -0 than for 0.

For example, where Math.atan2(0, -1) returns 3.141592653589793, Math.atan2(-0, -1) returns -3.141592653589793.

You can use this fact to simplify the equation for getting a result in the range of [0, 2π).

Notice what you get if you negate the X and Y values:

   X   |   Y   |  -X   |  -Y   |  Math.atan2(-Y,-X)
===========================================================
   1   |   0   |  -1   |  -0   | -1.00π (-3.141592653589793)
   1   |   1   |  -1   |  -1   | -0.75π (-2.356194490192345)
   0   |   1   |  -0   |  -1   | -0.50π (-1.5707963267948966)
  -1   |   1   |   1   |  -1   | -0.25π (-0.7853981633974483)
  -1   |   0   |   1   |  -0   |  0.00π (0)
  -1   |  -1   |   1   |   1   |  0.25π (0.7853981633974483)
   0   |  -1   |  -0   |   1   |  0.50π (1.5707963267948966)
   1   |  -1   |  -1   |   1   |  0.75π (2.356194490192345)

If you then add π to the result, you will get a value in the range [0, 2π).

Therefore you can use:

var theta = Math.atan2(-Y, -X) + Math.PI;
John S
  • 20,117
  • 7
  • 39
  • 52