Case Study 2 — The Shape of Every Letter: Polynomial Spaces Behind Fonts and Animation
Every curve you have ever seen on a screen — the swoop of a letter's serif, the arc of a logo animating into place, the path a cartoon character follows as it leaps — is, with overwhelming probability, a polynomial. Not a polynomial you would recognize from algebra class, written $a_0 + a_1 x + a_2 x^2 + \cdots$, but the same object dressed for design work, controlled by dragging a few dots called control points. The mathematics that makes this possible is the polynomial vector space $\mathbb{P}_n$ from Section 5.4, and the reason designers can blend, scale, and reshape curves so fluidly is that those curves live in a vector space and obey its axioms. This case study is pure computer graphics — no physics — and it shows the abstraction of Chapter 5 doing daily work in software you have used today.
Curves are vectors, and the vectors are polynomials
A designer drawing a smooth curve does not type coefficients. Instead they place a handful of control points and let the software fit a smooth curve to them. The most important such curve is the Bézier curve, named for Pierre Bézier, who developed it in the 1960s for designing car bodies at Renault [verify]. A quadratic Bézier curve is governed by three control points $P_0, P_1, P_2$ and is defined, for a parameter $t$ running from $0$ to $1$, by $$B(t) = (1-t)^2\,P_0 + 2(1-t)t\,P_1 + t^2\,P_2.$$ Look closely at the structure. The curve $B(t)$ is a linear combination of the three control points, with weights that are themselves polynomials in $t$: the functions $(1-t)^2$, $2(1-t)t$, and $t^2$. Those three weight-functions are the Bernstein basis of the quadratic polynomial space $\mathbb{P}_2$, and they are the building-block vectors here — the analog of $1, x, x^2$ but chosen because they have lovely design properties (they are always nonnegative on $[0,1]$ and sum to $1$, so the curve stays inside the "hull" of its control points). The control points are the coordinates of the curve in that basis. This is the chapter's central move — express a vector as a linear combination of building blocks — applied to curves.
# A quadratic Bezier curve is a linear combination of 3 control points.
import numpy as np
P0, P1, P2 = np.array([0, 0]), np.array([1, 2]), np.array([2, 0])
def bezier(t):
return (1-t)**2 * P0 + 2*(1-t)*t * P1 + t**2 * P2 # weights are basis polynomials
print(bezier(0.0)) # [0 0] -> starts at P0
print(bezier(1.0)) # [2 0] -> ends at P2
print(bezier(0.5)) # [1. 1.] -> the peak of the arc, pulled toward P1
At $t = 0$ the curve sits at $P_0$, at $t = 1$ it reaches $P_2$, and at $t = 0.5$ it bulges toward $P_1$ to the point $(1, 1)$ — exactly the smooth arc a designer wants. The curve is a vector in $\mathbb{P}_2$ (well, two of them — one polynomial for the $x$-coordinate, one for $y$), assembled by the scale-and-add recipe of Chapter 5.
Why blending curves "just works": closure
Here is the property that makes vector tools like Adobe Illustrator, Figma, and font editors feel so smooth, and it is the closure axiom in action. Suppose an animator has two curves — say, the shape of a logo at the start of an animation and its shape at the end — and wants to generate all the in-between frames by blending them. Blending curve $A$ and curve $B$ with a parameter $s \in [0,1]$ means forming $$C_s = (1-s)\,A + s\,B,$$ a linear combination of two curves. Because $\mathbb{P}_2$ is a vector space, $C_s$ is guaranteed to be another curve in $\mathbb{P}_2$ — a genuine quadratic Bézier curve the renderer knows how to draw — for every value of $s$. The closure axiom (Axiom 0) is the promise that you can never accidentally produce an object outside the space; the blend of two cubics is always a cubic, the average of two fonts is always a drawable font. Designers call this "interpolation" or "tweening," and it is the engine behind every morphing logo and every variable font that smoothly slides from light to bold.
# "Tweening" two curves is a linear combination -> closure guarantees a valid curve.
import numpy as np
A = np.array([0.0, 1.0, 2.0]) # coefficients of curve A in some basis
B = np.array([2.0, 1.0, 0.0]) # coefficients of curve B
for s in (0.0, 0.5, 1.0):
C = (1-s)*A + s*B # blend: still a vector in P_2, always drawable
print(f"s={s}:", C)
# s=0.0: [0. 1. 2.] (curve A)
# s=0.5: [1. 1. 1.] (the halfway curve)
# s=1.0: [2. 1. 0.] (curve B)
The reason a variable font can offer every weight between "thin" and "black," not just a handful of presets, is that the glyph outlines are vectors in a polynomial space and the in-between weights are linear combinations of the extremes. There is nothing to store for the intermediate weights; they are computed on the fly as combinations, because the space is closed under exactly that operation.
A subspace hiding in the design: constrained curves
The chapter's subspace idea shows up the moment a designer imposes a constraint. Suppose you require that a family of curves all pass through the origin at $t = 0$ — a common requirement when curves must connect seamlessly to a fixed anchor point. In the polynomial space, "the curve passes through the origin at $t=0$" is the condition $B(0) = \mathbf{0}$, a homogeneous constraint. As Section 5.7 showed, homogeneous constraints carve out subspaces: the set of all curves satisfying $B(0) = \mathbf{0}$ is closed under addition and scaling (blend two curves anchored at the origin and the blend is still anchored at the origin), so it is a subspace of the full curve space. Contrast a constraint like "the curve passes through the fixed point $(3, 1)$" — that is not homogeneous, the set is not a subspace (blending two such curves lands you at $(6,2)$, not $(3,1)$), and software must handle it differently (by translating to the origin, doing the linear work there, and translating back — the homogeneous-coordinate trick of Chapter 12). The clean split between "constraints that give subspaces" and "constraints that don't" is exactly the distinction the chapter drew, now visible in a font editor's anchor-point logic.
Why the abstraction earns its keep here
Notice, once more, what was not needed. The "vectors" were curves, not arrows. The "basis" was the Bernstein polynomials, not $\mathbf{e}_1, \mathbf{e}_2$. The "coordinates" were control points a designer drags with a mouse. Yet every operation — placing a curve, blending two of them, constraining a family to an anchor — was a vector-space operation, governed by the same eight axioms as arrows in the plane. A graphics programmer who knows only "linear algebra is matrix arithmetic" can implement Bézier curves by rote, but cannot see why tweening can never break or why anchored curves form a closed family; a programmer who learned the abstract definition of Chapter 5 sees that fonts and animations are linear algebra in a polynomial space and that the guarantees come straight from the axioms.
This is the same lesson as the equalizer of Case Study 1, in a completely different field — signal processing there, computer graphics here — and that is the point. The content could not be more different (sound waves versus letterforms), but the structure is identical: a vector space, building-block vectors, linear combinations, closure. Learn the structure once and you understand both, plus the dozen other settings the chapter listed. When you reach change of basis (Chapter 16), you will see that switching from the Bernstein basis to the power basis $1, x, x^2$ is the same kind of coordinate change as switching a sound between time and frequency — one more reason the climb to abstraction was worth it.
Forward references: linear combinations and span (Chapter 6); coordinates and bases, including the Bernstein vs. power basis (Chapter 15); switching bases for curves (Chapter 16); anchoring and translating curves via homogeneous coordinates (Chapter 12).