Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

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?

share|improve this question
    
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? –  BlueRaja - Danny Pflughoeft Jul 8 '11 at 2:22
4  
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. –  FxIII Jul 8 '11 at 7:04
    
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. –  jhocking Jul 9 '11 at 12:38
    
thanks people for the answers, now im regretting not paying more attention in class –  sutoL Jul 10 '11 at 12:30

6 Answers 6

up vote 52 down vote accepted

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.

share|improve this answer
5  
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. –  doppelgreener Jul 9 '11 at 6:17
    
Indeed, very important note right there. Updating my answer. –  Jesse Emond Jul 9 '11 at 12:02
    
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). –  jhocking Jul 9 '11 at 12:28
    
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. –  Jesse Emond Jul 9 '11 at 12:56
    
I'll change your wording then, because it sounds like you were saying the opposite. –  jhocking Jul 9 '11 at 12:59

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 radian_to_degrees(angle); // Because angle is in radian 360 degrees = 2*Pi radians
}
share|improve this answer
    
tan(a) = - tan(-a), the equation you wanted to express was perhaps tan(a) = tan(pi+a) –  Ali.S Jul 8 '11 at 9:06
    
@Gajooo yes, thank you! –  Sid Datta Dec 14 '12 at 21:26

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;
}
share|improve this answer
1  
"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. –  user744 Jul 8 '11 at 18:39
    
The code is still wrong. You're testing for y==0 then dividing by x in the other branch. –  Sam Hocevar Sep 10 '12 at 0:50

enter image description here

share|improve this answer
    
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(). –  jhocking Jul 9 '11 at 12:33
    
Go ahead: be my guest! I'll delete this answer after you're done. –  Gareth Rees Jul 9 '11 at 12:34
4  
No, no. Keep it up! It is credited and people should still upvote here for the diagram. –  Jesse Emond Jul 9 '11 at 12:52

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( x*x + y*y )

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)
share|improve this answer

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 ;
}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.