# Axes and Angles

from Red Blob Games
25 Sep 2019

I created this page for myself because I was using several different axes and angle systems and wanted to keep track of the formulas.

## 1  Axes#

In math, we typically have X pointing right and Y pointing up. But in 2D graphics for computer screens, including SVG and HTML5 Canvas, we usually have Y pointing down:

(Historical note: we use Y down because that’s how CRT electron guns scanned the lines for TVs. But IBM OS/2 used Y up for its 2D graphics!)

When working with 3D you have to be extra careful about axes. Both DirectX and OpenGL have Y pointing up, but DirectX and OpenGL textures have Y pointing down. DirectX has a Z axis pointing away from the screen and OpenGL has a Z axis pointing towards the screen. Unity uses Y pointing up for graphics and Y pointing down for UI elements.

## 2  Angles#

In math we have a standard angle system where 0° is east, 90° north, and angles grow counterclockwise. But in navigation we have a compass angle system where 0° is north, 90° east, and angles grow clockwise. And you might also have a math angle system flipped upside down to match the screen.

Either way, angles are a little tricky because of the wraparound. Unit vectors are often nicer. But when working with angles I use separate functions to tell me how far I have to turn left vs how far I have to turn right. Note that you may have to reverse the names depending on which coordinate system you use.

```function mod(value, modulo) {
return ((value % modulo) + modulo) % modulo
}

function degreesLeft(startDeg, endDeg) {
return mod(endDeg - startDeg, 360)
}

function degreesRight(startDeg, endDeg) {
return mod(startDeg - endDeg, 360)
}

function degreesApart(startDeg, endDeg) {
return Math.min(degreesLeft(startDeg, endDeg),
degreesRight(startDeg, endDeg))
}

function test(expr, expected) {
console.log(expr, "=", eval(expr), ", should be", expected)
}

test("degreesLeft(350, 10)",   20)
test("degreesLeft(10, 350)",  340)
test("degreesRight(350, 10)", 340)
test("degreesRight(10, 350)",  20)
test("degreesApart(10, 10)",  0)
test("degreesApart(10, 350)",  20)
test("degreesApart(10, 90)",  80)
test("degreesApart(10, 190)",  180)
test("degreesApart(10, 40)",   30)
```

There’s a shorter way to express the non-directional version on this stackoverflow answer.

```function mod(value, modulo) {
return ((value % modulo) + modulo) % modulo
}

function degreesApart(startDeg, endDeg) {
let diff = mod(endDeg - startDeg, 360)
return 180 - Math.abs(Math.abs(diff) - 180)
}

function test(expr, expected) {
console.log(expr, "=", eval(expr), ", should be", expected)
}

test("degreesApart(10, 10)",  0)
test("degreesApart(10, 350)",  20)
test("degreesApart(10, 90)",  80)
test("degreesApart(10, 190)",  180)
test("degreesApart(10, 40)",   30)
```

## 3  Trigonometry#

These rules are independent of the coordinate systems you’re using:

```θ = atan2(A, B)
A = sin(θ)
B = cos(θ)
```

They always have to match up; it’s a nice way to double check consistency.

(Is this right? need to double check)

I find it easiest to remember things when θ = atan2(y, x), either math angles + math axes, or screen angles + screen axes, but sometimes I need to use another system for the project.

Email me , or tweet @redblobgames, or comment: