On this page
Trigonometry in Code
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.0const 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)Bug gallery
- Degrees into radian functions.
Math.sin(90)≈ 0.894, not 1. Convert:Math.sin(d * Math.PI/180). ataninstead ofatan2.atan(dy/dx)breaks whendx ≤ 0ordx = 0. Useatan2(dy, dx).atan2argument order. It is(y, x)in Python, JS, C, Rust, Go. Swapping rotates your answer 90°.- y-down screens. Canvas y grows downward, so
sinappears flipped vs. math textbooks. Test with 90°: does your object go down (screen) or up (math)? acos/asindomain errors. Dot-product rounding can yield 1.0000000002 → NaN. Clamp to \([−1, 1]\) first.tannear asymptotes.tan(π/2)is huge, not infinite. Guard denominators:if abs(cos) < 1e-9: ....- 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.0Mini-project ideas
- Analog clock (Canvas/SVG): 60 ticks via
circle_points, hands via angle = fraction × 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\).
- Audio beep (WebAudio):
oscillator.frequency+ sine gain envelope from Recipe 3. - 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.