Cheat sheet

$$ x = r\cos\theta, \qquad y = r\sin\theta, \qquad \theta = \text{atan2}(y, x) $$
$$ \text{rad} = \text{deg}\cdot\tfrac{\pi}{180}, \qquad \text{deg} = \text{rad}\cdot\tfrac{180}{\pi} $$

All standard-library trig takes radians: Python math.sin/cos/tan/asin/acos/atan/atan2, JS Math.sin/cos/tan/asin/acos/atan/atan2.

Recipe 1: place objects on a circle

Clocks, radial menus, orbit systems:

import math
def circle_points(n, radius, cx=0.0, cy=0.0):
    return [
        (cx + radius * math.cos(2 * math.pi * i / n),
         cy + radius * math.sin(2 * math.pi * i / n))
        for i in range(n)
    ]
print(circle_points(4, 10))  # E, N, W, S in math coords (y up)
function circlePoints(n, radius, cx = 0, cy = 0) {
  return Array.from({ length: n }, (_, i) => {
    const t = 2 * Math.PI * i / n;
    return [cx + radius * Math.cos(t), cy + radius * Math.sin(t)];
  });
}

Note: screen coordinates have y down, so on Canvas/SVG the circle appears mirrored (clockwise). Negate y or add \(\pi\) if you need math orientation.

Recipe 2: rotate a point / sprite

$$ x' = x\cos\theta - y\sin\theta, \qquad y' = x\sin\theta + y\cos\theta $$
import math
def rotate(x, y, angle_deg):
    r = math.radians(angle_deg)
    c, s = math.cos(r), math.sin(r)
    return (x * c - y * s, x * s + y * c)
print(rotate(1, 0, 90))  # (0, 1)

Canvas equivalent: ctx.rotate(angleInRadians) — again radians, and positive is clockwise because y is down.

Recipe 3: smooth oscillation

Any idle animation, pulse, or tone:

import math
def oscillate(t, *, period=2.0, lo=0.0, hi=1.0, phase=0.0):
    mid = (hi + lo) / 2
    amp = (hi - lo) / 2
    return mid + amp * math.sin(2 * math.pi * (t / period) + phase)
# oscillate(0.5, period=2) -> 0.5 rising toward 1.0 at t=1.0
const oscillate = (t, period = 2, lo = 0, hi = 1, phase = 0) =>
  (hi + lo) / 2 + ((hi - lo) / 2) * Math.sin(2 * Math.PI * (t / period) + phase);

Recipe 4: distance and bearing (maps / games)

import math
def polar(dx, dy):
    r = math.hypot(dx, dy)
    theta = math.atan2(dy, dx)  # radians, full-circle safe
    return r, theta
print(polar(-1, -1))  # (1.414, -2.356 rad = -135 deg)
  1. Degrees into radian functions. Math.sin(90) ≈ 0.894, not 1. Convert: Math.sin(d * Math.PI/180).
  2. atan instead of atan2. atan(dy/dx) breaks when dx ≤ 0 or dx = 0. Use atan2(dy, dx).
  3. atan2 argument order. It is (y, x) in Python, JS, C, Rust, Go. Swapping rotates your answer 90°.
  4. y-down screens. Canvas y grows downward, so sin appears flipped vs. math textbooks. Test with 90°: does your object go down (screen) or up (math)?
  5. acos/asin domain errors. Dot-product rounding can yield 1.0000000002 → NaN. Clamp to \([−1, 1]\) first.
  6. tan near asymptotes. tan(π/2) is huge, not infinite. Guard denominators: if abs(cos) < 1e-9: ....
  7. Float dust. sin(π) ≈ 1.2e-16, not 0. Round for display: round(x, 9) or snap tiny values to 0.
import math
def clean(x, eps=1e-9): return 0.0 if abs(x) < eps else x
print(clean(math.sin(math.pi)))  # 0.0

Mini-project ideas

  1. Analog clock (Canvas/SVG): 60 ticks via circle_points, hands via angle = fraction × 2π.
  2. Projectile visualizer: \(x = v_0\cos\theta \cdot t\), \(y = v_0\sin\theta \cdot t − g t^2/2\). Add a slider for \(\theta\).
  3. Audio beep (WebAudio): oscillator.frequency + sine gain envelope from Recipe 3.
  4. Lissajous figure: plot \(x = \sin(3t)\), \(y = \sin(4t + \pi/4)\) for \(t \in [0, 2\pi)\). Pure trig art.

Where to go next

Revisit the theory pages with your project in mind: Unit Circle for rotation signs, Graphs for animation timing, Solving Triangles for layout geometry. Then break things in code — that is where the intuition sticks.

Next: JS Playground — run trig code live, on a canvas or on the page.