48
\$\begingroup\$

I am having some trouble understanding Math.tan() and Math.atan() and Math.atan2().

I have basic knowledge of trigonmetry but the usage of SIN, COS, and TAN etc for game development is very new to me.

I am reading on some tutorials and I see that by using tangent we can get the angle in which one object needs to be rotated by how much to face another object for example my mouse. So why do we still need to use atan or atan2?

\$\endgroup\$
4
  • \$\begingroup\$ atan is used to determine the angle, useful for a thousand different things. Do you have an actual question about its use, or are you just looking for general math help? \$\endgroup\$ Jul 8, 2011 at 2:22
  • 5
    \$\begingroup\$ You definitely need to understand the math/geometry behind those function; once you master them, they will become a part of your "world understanding", like the basic grammar you use everyday to speak. Once you are able to "speak the math/geometry" you will see that those functions are simpy tools to achieve a result, the most natural to use. \$\endgroup\$
    – FxIII
    Jul 8, 2011 at 7:04
  • \$\begingroup\$ Those tutorials are either wrong or you misunderstood. You use atan2() to get the angle from one object to another. How that works is explained below. \$\endgroup\$
    – jhocking
    Jul 9, 2011 at 12:38
  • 1
    \$\begingroup\$ thanks people for the answers, now im regretting not paying more attention in class \$\endgroup\$
    – sutoL
    Jul 10, 2011 at 12:30

7 Answers 7

97
\$\begingroup\$

The tangent formula is this:

tan(angle) = opposite/adjacent

Refer to this drawing:

Diagram of a right-angled triangle, with an angle theta and its opposite and adjacent sides marked

Where a is the adjacent side, o is the opposite side and theta is the angle. Similarly, sine and cosine are sin(ang)=o/h and cos(ang)=a/h where h is the long side: http://www.mathwords.com/s/sohcahtoa.htm

Meanwhile atan (short for arc-tangent, also known as the inverse tangent) is the reverse of tan, like so:

atan(opposite/adjacent) = angle

Thus, if you know the values of both the opposite and adjacent sides (for example, by subtracting the object's coordinates from the mouse coordinates) you can get the value of the angle with atan.

In game development though, it can happen fairly often that the adjacent side is equal to 0 (e.g. the x coordinate of a vector being 0). Remembering that tan(angle) = opposite/adjacent the potential for a disastrous divide-by-zero error should be clear. So a lot of libraries offer a function called atan2, which lets you specify both the x and y parameters, to avoid the division by zero for you and give an angle in the right quadrant.

atan2 diagram

(diagram courtesy of gareth, please vote up his answer too)


The use of trigonometry in game development is pretty common, especially with vectors, but usually libraries hide the trigonometry work for you. You can use sin/cos/tan for a lot of tasks which involve geometric manipulations to find a value from a triangle. All you need is 3 values (side lengths / angle values) to find the other values of a rectangle triangle, so it's quite useful.

You can even use the "cycling" nature of the sine and cosine functions for special behaviors in a game, e.g. I've seen cos/sin used a lot to make an object turn around an other one.

\$\endgroup\$
8
  • 8
    \$\begingroup\$ It's worth noting Wikipedia describes other usages for Atan2 (not atan) than just avoiding the division by zero. For instance, it corrects itself for the quadrant being used, where normally you'd have to do all that yourself. \$\endgroup\$ Jul 9, 2011 at 6:17
  • \$\begingroup\$ Indeed, very important note right there. Updating my answer. \$\endgroup\$ Jul 9, 2011 at 12:02
  • \$\begingroup\$ Didn't you get tan and atan backwards in your first long paragraph? You'd use atan to get the angle (ie. reverse the equation) and tan to get the ratio of the sides (ie. exactly what the equation says). \$\endgroup\$
    – jhocking
    Jul 9, 2011 at 12:28
  • \$\begingroup\$ Well if you know o/a is equal to e.g. 3, then if you want the angle you do atan(3), that's what I meant: if you want to isolate the angle, you use atan on the ratio. If you want to isolate the ratio, you use tan on the angle. \$\endgroup\$ Jul 9, 2011 at 12:56
  • \$\begingroup\$ I'll change your wording then, because it sounds like you were saying the opposite. \$\endgroup\$
    – jhocking
    Jul 9, 2011 at 12:59
63
\$\begingroup\$

enter image description here

\$\endgroup\$
3
  • 1
    \$\begingroup\$ Would it be impolite to edit the top answer to have this diagram in it? This diagram is great and would fit well right after Jesse's written explanation of atan2(). \$\endgroup\$
    – jhocking
    Jul 9, 2011 at 12:33
  • 1
    \$\begingroup\$ Go ahead: be my guest! I'll delete this answer after you're done. \$\endgroup\$ Jul 9, 2011 at 12:34
  • 7
    \$\begingroup\$ No, no. Keep it up! It is credited and people should still upvote here for the diagram. \$\endgroup\$ Jul 9, 2011 at 12:52
12
\$\begingroup\$

Here's a slightly different way of thinking about trig functions - including atan() and atan2() - that I find helpful (explanations in terms of "opposite/adjacent" just confuse me for some reason).

x, y, r, theta

You can get from one point to another by moving x units horizontally and y units vertically (called rectangular or Cartesian coordinates) or by moving distance r at an angle of Ɵ (called polar coordinates in 2D).

Say we have a polar coordinate (r,Ɵ) and we want to convert it to (x,y).

cos(Ɵ) gives you the proportion of r that lies along the x axis:

  • If r = 1 then x = cos(Ɵ).
  • If r = 100 then x = 100 * cos(Ɵ).
  • In general x = r * cos(Ɵ).

Likewise sin(Ɵ) gives you the proportion of r that lies along the y axis:

  • If r = 1 then y = sin(Ɵ).
  • If r = 100 then y = 100 * sin(Ɵ).
  • In general y = r * sin(Ɵ).

How about converting rectangular coordinate (x,y) into polar coordinate (r,Ɵ)?

r is the hypotenuse of the right triangle formed by x and y, so:

  • r = sqrt( xx + yy )

tan(Ɵ) gives the slope - the rise over the run - of the line with length r. So:

  • tan(Ɵ) = y/x
  • Ɵ = atan(y/x)

However, when performing y/x, calculating 3/4 gives the same answer as calculating -3/-4. Likewise -3/4 gives the same answer as 3/-4. So we have atan2(y,x) that handles the individual signs correctly and prevents a divide-by-zero/infinity error.

  • Ɵ = atan2(y,x)
\$\endgroup\$
4
\$\begingroup\$

Jesse and Sid are basically right, but I suspect you are really after insight into the problem.

Atan2() is needed as atan() doesn't tell you the angle from the horizontal you need as it doesn't cope with quadrants.

This means that using atan for vectors (-2,2) and (2,-2) will give the same value. You would then to switch on the sign of yours arguments and add pi to the result. In addition, you have the divide by zero special case to consider that Jesse mentioned. Also atan2() works better than atan when x is close to 0

So you if you want the angle of a vector between -pi and pi

x = -2
y = 2
angle = Math.Atan2(y, x)

or

x = -2
y = 2
angle = calculateAngle(y, x);

double CalculateAngle(double y, double x)
{
    double angle = 0;
    if (x == 0)
    {
        if (y == 0)
            angle = 0;
        else if (y > 0)
            angle = Math.PI/2;
        else
            angle = -Math.PI/2;
    }
    else
    {
        angle = Math.Atan(y/x);
        if (x < 0)
        {
            if (y > 0)
            {
                angle += Math.PI;
            }
            else if (y < 0)
            {
                angle -= Math.PI;
            }
            else
            {
                angle = Math.PI;
            }
        }
    }
    return angle;
}
\$\endgroup\$
2
  • 1
    \$\begingroup\$ "This means that using atan for vectors (-2,2) and (2,2) will give the same value." If this is the case your atan is incredibly broken, because one of them is should be -π/4 and the other π/4. Shame on everyone who voted this garbage up. \$\endgroup\$
    – user744
    Jul 8, 2011 at 18:39
  • \$\begingroup\$ The code is still wrong. You're testing for y==0 then dividing by x in the other branch. \$\endgroup\$ Sep 10, 2012 at 0:50
1
\$\begingroup\$

One use for atan2 I found in my code is "signed angle".

Normally the way you'd find the angle between two vectors is

inline float angleWith( const Vector2f& o ) const
{
    return acosf( this->normalizedCopy().dot(o.normalizedCopy()) ) ;
}

But this doesn't tell you which one "leads" (ie is "further ahead clockwise" than the other). This information may be important for gesture tracking.

You could find the angle from the x axis (1,0) for both vectors, but there is this nasty problem of ambiguity: a vector with an angle of 315 degrees returns 45 degrees using the cos method above, and so does an angle of 45 degrees. You could do a sign check on y to fix that, or you could use atan2.

// Returns + if this leads o.
// more expensive than unsigned angle.
inline float signedAngleWith( const Vector2f& o ) const
{
  float aThis = atan2f( y, x );
  float aO = atan2f( o.y, o.x ) ;
  return aThis - aO ;
}
\$\endgroup\$
0
\$\begingroup\$

Please Note atan is not broken. arctan or tan inverse is only a function between -PI/2 and PI/2. It repeats this pattern but then it isn't a function which is a problem for a computer as it doesn't handle multiple answers.

This is the same for asin between -PI/2 and PI/2 and acos between 0 and PI. These are the simplest ranges for a function to occur. For atan and asin it goes from its most negative to its most positive. For acos its goes from its most positive to its most negative. (this assists in interpolating more accurate answers)

so asin, acos and atan are the mathematical functions.

atan2 however is much more usefull for programming as it provides the complete revolution (PI in radians or 360 degrees or 400 gradians). Note they only produced one for tan not for sin or cos. Tan is the only one that uses horizontal and vertical (x,y)

\$\endgroup\$
0
\$\begingroup\$

I will clarify a few things in a concise manner. Please refer to trigonometry tutorials online for a detailed explanation.

Let a be an angle. Then tan(a) = tan(a+2*pi).

atan is tan inverse, that is, gives you the angle given the tan. When you call atan(tan(a+2*pi)), the answer will be a. This will be inadequate for your application.

atan2 will take 2 arguments to help this exact situations. atan takes x and y, which are basically cos(a) and sin(a).

atan2(sin(a), cos(a)) = a atan2(sin(a+2*pi), cos(a+2*pi)) = a+2*pi /* sin and cos has different signs, leading to a different answer */

Please find some tutorials to explain why this is this way.

Your code should be something like this:

if (mouseMoved)
{
  double angle = atan2(mousey - objecty, mousex - objectx);

  object. setTransform to Rotate(angle);

  // If you want to print it
  print angle * Mathf.Rad2Deg; // Because angle provided is in radians
}
\$\endgroup\$
1
  • \$\begingroup\$ tan(a) = - tan(-a), the equation you wanted to express was perhaps tan(a) = tan(pi+a) \$\endgroup\$
    – Ali1S232
    Jul 8, 2011 at 9:06

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .