The Gram-Schmidt process turns any set of linearly independent vectors {v1, v2, v3} into an orthonormal basis {e1, e2, e3} — vectors that are mutually perpendicular and unit length — by repeatedly subtracting off the part of each vector that already lies along the previous ones:
proj_u(v) = (v · u / u · u) u
u1 = v1
u2 = v2 − proj_u1(v2)
u3 = v3 − proj_u1(v3) − proj_u2(v3)
e_i = u_i / |u_i|
Each subtraction removes exactly the component of the new vector that overlaps with the space already spanned, leaving only the genuinely "new" direction. Normalizing that leftover gives a unit vector perpendicular to every earlier one — which is why e1 always points exactly along v1: there is nothing to subtract from the first vector.
- v2, v3 sliders — move the two free input vectors; the orthonormal frame e1/e2/e3 and the dashed projection arrows update live.
- Show projections — draws the projection of v2 onto u1, and of v3 onto u1 and u2, the exact quantities the formula above subtracts.
- Animate — sweeps v2 and v3 through a continuous rotation so you can watch the orthonormal frame track a moving input in real time.
- det(Q) — the determinant of the matrix whose columns are e1, e2, e3; it is always ±1 for an orthonormal basis (+1 = right-handed), since Gram-Schmidt preserves orientation but rescales lengths to exactly 1.
- Volume of span(v1,v2,v3) — |det[v1 v2 v3]|, the volume of the parallelepiped the raw vectors sweep out; comparing it to det(Q) = 1 shows how orthonormalization discards magnitude information while keeping direction and handedness.
This is the algorithm behind QR decomposition, used throughout numerical linear algebra (least-squares fitting, eigenvalue solvers, computer-graphics camera bases) to replace a numerically messy set of vectors with a clean orthonormal frame.