Garry's Mod Wiki

Tutorials - Trigonometry


Trigonometry is a really useful tool to have in your coder's utility belt, and lots of people have a hard time grasping Sine and Cosine (and Tangent), so here's a crash course tutorial on their use.

Trigonometry is the math of right triangles and circles.


First, let's look at SOH, CAH, TOA:

  • SOH = Sine equals Opposite over Hypotenuse
  • CAH = Cosine equals Adjacent over Hypotenuse
  • TOA = Tangent equals Opposite over Adjacent

But what does this mean?

The Hypotenuse of a right triangle is the longest of the three sides. It's always on the opposite end of the right angle. The other two sides aren't uniquely named.

So depending on our situation, we can use one of the three equations to find out all we need to know about a right triangle. All we need is the length of one of the three sides and the degree of one of the two non-right angles. Refer to this diagram (not to scale):

If we replace those sides with a and b, with the Hypotenuse being c, with the angle we know being ang, we can use this equation to find the length of side b. Here is a Lua example:

local a = 8 local b -- we're going to find out b. This is our "Opposite" side. local c = 16 local ang = 30 ang = math.rad( ang ) -- Turn our degrees into radians. This is a requirement for Lua. Don't worry too much about it now. -- Remember Sine equals Opposite over Hypotenuse. -- That is, the sine of the angle is equal to the opposite leg's length divided by the Hypotenuse's length. -- math.sin( ang ) == b / c -- Here is the same equation, solved for b: b = math.sin( ang ) * c -- Lua will calculate the sin of ang, as such: -- math.sin( math.rad( 30 ) ) = .5 print( b == .5 * 16 ) --Will output true.

Believe it or not, these basic right triangle calculations have SO MANY USES. Over 2200 years ago, mathematicians used these functions to calculate the radius of Earth. It's used literally every second of every day in GPS software (hence the term triangulation). It's used by police to track the location of a phone call. SOH CAH TOA is the foundation of Trigonometry.

The three trigonometric functions are math.sin, math.cos, and math.tan.

Unit Circle

When we investigate the origins of Sine and Cosine, we can learn a thing or two about the fundamental properties of a circle. Consider the following:

We have a circle with radius 1. In this circle, we have radius line which is tilted 30 degrees (counterclockwise, always counterclockwise) from the circle's right horizontal axis. Because it is a radius line, its length is equal to the radius of the circle, which is 1 in this case.

So what is the length of b? If we recall SOH, we see that Sin( ang ) = Opposite / Hypotenuse. Plug in our values, and Sin( 30 ) = b / 1. Seeing as how any number divided by 1 is itself, we can conclude that:

In a circle of radius 1, the Y-value of a point on a circle relative to the center of the circle is equal to the sine of the angle. In a circle of radius 1, the X-value of a point on a circle relative to the center of the circle is equal to the cosine of the angle.

That is,

y = math.sin( ang ) x = math.cos( ang )

Which we can see here:

But not all circles are of radius 1. When we have a circle that is larger than radius 1, we just multiply.

y = math.sin( ang ) * radius x = math.cos( ang ) * radius

Furthermore, we've been assuming that our circle is centered at point (0,0). If our circle's center is (100,453), we add. This is our complete formula:

y = math.sin( ang ) * radius + originY x = math.cos( ang ) * radius + originX

This is useful in GLua for drawing circles, arranging props in circles, and basically any other circle-based code. Here is an example which draws squares:

function PointOnCircle( ang, radius, offX, offY ) ang = math.rad( ang ) local x = math.cos( ang ) * radius + offX local y = math.sin( ang ) * radius + offY return x, y end local numSquares = 36 --How many squares do we want to draw? local interval = 360 / numSquares local centerX, centerY = 200, 500 local radius = 120 hook.Add("HUDPaint","Draw a circle of boxes!", function() for degrees = 1, 360, interval do --Start at 1, go to 360, and skip forward at even intervals. local x, y = PointOnCircle( degrees, radius, centerX, centerY ) draw.RoundedBox( 4, x, y, 30, 30, Color(255,255,0) ) end end)


WOW! SO USEFUL! Radial menus, circular health bars, chairs arranged around a circular table, ellipses, sound waves, and MUCH MORE are possible with Trigonometry.

Inverse Functions

The inverse function of a Trigonometric function is called the arc-function.

The three inverse trigonometric functions are math.asin, math.acos, and math.atan or math.atan2.

Arc functions work like so:

--The following two equations are equivalent: sin( a ) = b / c a = arcsin( b / c ) --The following two equations are equivalent: cos( a ) = b / c a = arccos( b / c )

These are useful for doing reverse math, for example:

-- We know the length of A and B, and we want to find angle THETA, which is adjacent to B local A = 2 local B = 4 -- sin( ang ) == A / B -- ang == arcsin( A / B ) local ang = math.asin( A / B ) print(ang) -- Outputs 30; sin( 30 ) == .5 == 2/4 == A/B

These functions are useful if the unknown variable in question is your angle. There is a special Arc-Tangent function for programming called math.atan2.

Think of tan(ang) as giving the slope - the rise over the run - of a line. So:

tan( ang ) = y / x ang = 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.

ang = atan2( y, x )

atan2's use is to get the angle of a line with a slope m as in the equation y = mx + b


Trigonometry is required to create any circular structure, and to do math with right triangles. It is also useful to find the angle of a line given its slope.

I hope you learned something useful here!