Numerical Analysis

Bézier Curves: Smooth Curves from Control Points

Bézier Curves are polynomial curves that turn a short list of control points into one smooth, predictable arc. A cubic Bézier takes four points P₀, P₁, P₂, P₃ and produces a curve B(t), for t ∈ [0,1], that starts at P₀, ends at P₃, and is pulled toward the two interior points without ever passing through them. The curve is a weighted average of the control points where the weights are the Bernstein polynomials: B(t) = ∑ Bᵢ(t)·Pᵢ. Because those weights are always ≥ 0 and always sum to 1, every point of the curve lies inside the convex hull of its control points — which is exactly why designers, font engineers, and plotters can trust the shape they draw.
  • Named afterPierre Bézier (Renault, ~1962)
  • Also devised byPaul de Casteljau (Citroën, 1959)
  • Cubic formulaB(t) = (1−t)³P₀ + 3(1−t)²t·P₁ + 3(1−t)t²·P₂ + t³P₃
  • BasisBernstein polynomials Bᵢⁿ(t) = C(n,i)(1−t)ⁿ⁻ⁱtⁱ
  • Degree n curven+1 control points; lies in their convex hull
  • EndpointsB(0) = P₀, B(1) = Pₙ (interpolates only the ends)

Watch the 60-second explainer

A condensed visual walkthrough — narrated, captioned, under a minute.

The Definition: A Curve as a Weighted Average of Points

A Bézier curve of degree n is defined by n+1 control points P₀, P₁, …, Pₙ (each a point in the plane or in space) and a single parameter t that runs from 0 to 1. The curve is

B(t) = ∑ᵢ₌₀ⁿ Bᵢⁿ(t)·Pᵢ,    where  Bᵢⁿ(t) = C(n,i)·(1−t)ⁿ⁻ⁱ·tⁱ.

The weights Bᵢⁿ(t) are the Bernstein polynomials, and C(n,i) = n!/(i!(n−i)!) is a binomial coefficient. The whole formula is nothing more sinister than the binomial expansion of ((1−t) + t)ⁿ = 1, with each term ‘tagged’ by a control point. For the ubiquitous cubic case (n = 3, four points) this reads out as

B(t) = (1−t)³P₀ + 3(1−t)²t·P₁ + 3(1−t)t²·P₂ + t³P₃.

Notice this is genuinely a weighted average: at every t the four coefficients are ≥ 0 and add to exactly 1. So B(t) is always a convex combination of the four control points — a fact with real teeth, as we'll see.

de Casteljau's Algorithm: The Curve Without the Polynomial

You can evaluate B(t) by plugging into the Bernstein formula, but there is a far more elegant recipe that predates Bézier's publication — Paul de Casteljau's construction (Citroën, 1959). It is pure repeated linear interpolation, or lerping.

Write lerp(A, B, t) = (1−t)A + t·B, the point a fraction t of the way from A to B. Then:

  • Level 1: interpolate along each control segment. P₀¹ = lerp(P₀,P₁,t), P₁¹ = lerp(P₁,P₂,t), P₂¹ = lerp(P₂,P₃,t). Three new points.
  • Level 2: interpolate along the segments joining those. P₀² = lerp(P₀¹,P₁¹,t), P₁² = lerp(P₁¹,P₂¹,t). Two points.
  • Level 3: one final lerp. B(t) = lerp(P₀²,P₁²,t).

The single surviving point is the curve point. As t sweeps 0→1 the whole scaffold of lines slides and collapses to a moving dot that traces B(t). It is numerically stable (only convex combinations, so no error blow-up), needs no factorials, and it hands you a bonus: the last-level pair (P₀², P₁²) spans the tangent direction B′(t), and cutting the algorithm off at parameter t splits the curve into two sub-Béziers — the basis of adaptive subdivision and of clipping algorithms.

A Fully Worked Cubic Example

Take the four control points P₀ = (0, 0), P₁ = (1, 2), P₂ = (3, 2), P₃ = (4, 0), and evaluate the curve at the midpoint t = ½. First the Bernstein weights at t = ½: (1−t)³ = ⅛, 3(1−t)²t = ⅜, 3(1−t)t² = ⅜, t³ = ⅛. They sum to ⅛+⅜+⅜+⅛ = 1, as required.

Now the x-coordinate: ⅛·0 + ⅜·1 + ⅜·3 + ⅛·4 = 0 + 0.375 + 1.125 + 0.5 = 2. And y: ⅛·0 + ⅜·2 + ⅜·2 + ⅛·0 = 0 + 0.75 + 0.75 + 0 = 1.5. So B(½) = (2, 1.5).

Cross-check with de Casteljau at t = ½ (each lerp is just the midpoint): Level 1 gives P₀¹ = (0.5,1), P₁¹ = (2,2), P₂¹ = (3.5,1). Level 2 gives P₀² = (1.25,1.5), P₁² = (2.75,1.5). Level 3: midpoint of those two = (2, 1.5). ✓ Identical — as it must be, since both compute the same polynomial.

The tangent there points along P₁² − P₀² = (1.5, 0), i.e. horizontal — the curve is flat at its top, matching the symmetric ‘hill’ these points describe. And note B(½) = (2, 1.5) sits strictly below the interior points at height 2: the curve is pulled toward P₁, P₂ but never reaches them.

Why the Properties Hold: Convex Hull, Endpoints, Tangents

Three headline guarantees fall straight out of the definition, and understanding why is what separates using Béziers from trusting them.

Endpoint interpolation. At t = 0 every Bernstein weight vanishes except B₀ⁿ(0) = (1−0)ⁿ = 1, so B(0) = P₀. Symmetrically B(1) = Pₙ. The curve nails its two ends and only its two ends.

Convex-hull containment. Because the weights are non-negative and sum to 1 for all t ∈ [0,1] (they are literally the terms of ((1−t)+t)ⁿ = 1), B(t) is a convex combination of the Pᵢ. A convex combination can never leave the convex hull of its points. Practical payoff: the curve can't ‘surprise’ you by wandering off — bounding-box and collision tests on the control polygon are conservative and cheap.

Tangent control. Differentiating, B′(t) = n·∑ᵢ₌₀ⁿ⁻¹ Bᵢⁿ⁻¹(t)·(Pᵢ₊₁ − Pᵢ) — itself a Bézier curve of degree n−1 over the difference vectors. At the ends this collapses to B′(0) = n(P₁ − P₀) and B′(1) = n(Pₙ − Pₙ₋₁). So the first and last control-polygon edges are exactly tangent to the curve, and their lengths set the initial ‘speed’. This is precisely the handle you grab in Illustrator or Figma.

Where It Matters, and How to Chain Curves

Bézier curves are the mathematical DNA of vector graphics. Every glyph in a PostScript or OpenType font is built from quadratic (TrueType) or cubic (Type 1 / CFF) Béziers; SVG's C and Q path commands are literally cubic and quadratic Béziers; CSS animation timing functions are cubic Béziers on the unit square. The reasons are the guarantees above plus affine invariance: transforming the control points and then drawing gives the same result as drawing and then transforming — so a rotated letter is exact, not resampled.

A single Bézier of high degree is unwieldy (moving one point wobbles the entire curve, and degree-n polynomials oscillate). The fix used everywhere is to chain low-degree pieces into a Bézier spline (a piecewise curve). To join two cubic segments smoothly you make them share an endpoint (C⁰), and for a smooth tangent (G¹/C¹) you make the incoming and outgoing handles collinear across the joint: Pₙ, the shared point, and the neighbouring control points must lie on one line. Enforce equal handle lengths too and you get C¹ continuity. This local, piecewise philosophy — with each piece still convex-hull-bounded — is what generalises to B-splines and their rational cousins NURBS, the workhorses of CAD, where a weighted (rational) form can represent exact circles and conics that ordinary polynomial Béziers cannot.

Pitfalls, Limits, and the Degree Question

Béziers do not interpolate their interior points. The single most common beginner error is expecting the curve to pass through P₁ and P₂. It doesn't — those are attractors, not waypoints. If you need the curve to hit a set of points, you must solve for control points (curve fitting) or use an interpolating spline instead.

High degree is a trap. You can fit n+1 arbitrary points with one degree-n Bézier, but the result inherits the Runge-style oscillations of high-degree polynomials, and evaluation cost grows (de Casteljau is O(n²)). Real systems keep degree at 2 or 3 and add more segments, not more points per segment.

No local control in a single segment. Because every Bernstein weight is nonzero on the open interval (0,1), nudging any one control point perturbs the entire arc. This is a feature for a designer tuning one letter but a liability for large models — which is again why B-splines, with their locally-supported basis functions, dominate engineering.

The subtle part — arc length. B(t) is smooth and easy to evaluate, but t is not proportional to distance along the curve. Equal steps in t give unequal spacing on screen; ‘constant-speed’ traversal (for a dot moving along the path, or evenly dashed strokes) requires reparametrising by arc length, which has no closed form for cubics and is done numerically. Forgetting this produces animations that visibly speed up and slow down for no apparent reason.

Bézier curves versus two common alternatives for the same job of drawing a smooth curve through/near given points.
PropertyBézier (single segment)B-splineCubic interpolating spline
Passes through pointsOnly the two endpointsNone of the control points (in general)All data points (interpolates)
Local controlNo — moving one point reshapes the whole curveYes — each point affects only a few spansNo — a global tridiagonal solve
Convex-hull guaranteeYes (whole curve)Yes (per span)No
Degree vs point countDegree grows with points (n+1 pts ⇒ degree n)Fixed low degree, many pointsPiecewise cubic, C² by construction
Typical useFonts, vector art, single arcsCAD/CAM surfaces, animation pathsScientific data interpolation

Frequently asked questions

Does a Bézier curve pass through its control points?

Only the first and last. B(0) = P₀ and B(1) = Pₙ exactly, because at those parameter values every Bernstein weight is zero except one. All interior control points merely pull the curve toward themselves without being touched — they set direction and ‘tension’, not position on the curve.

What's the difference between a quadratic and a cubic Bézier?

A quadratic has 3 control points and formula B(t) = (1−t)²P₀ + 2(1−t)t·P₁ + t²P₂ — a single parabola arc, used in TrueType fonts. A cubic has 4 points, B(t) = (1−t)³P₀ + 3(1−t)²t·P₁ + 3(1−t)t²·P₂ + t³P₃, and can form an S-shape (one inflection), which is why SVG, PostScript, and CSS timing curves use cubics.

Why use de Casteljau's algorithm instead of the Bernstein formula?

Both give the identical point, but de Casteljau uses only repeated linear interpolation between actual points — every intermediate result is a convex combination, so it is numerically stable and needs no factorials. It also yields the tangent for free (the final-level segment) and splits the curve into two sub-Béziers at t, which powers subdivision, rendering, and intersection algorithms.

What is the convex-hull property and why does it matter?

Every point of the curve lies inside the convex hull (the smallest convex polygon) of its control points. This holds because B(t) is a weighted average whose weights are ≥ 0 and sum to 1 for all t ∈ [0,1]. It matters practically: bounding boxes and collision/clipping tests on the easy-to-compute control polygon are guaranteed to contain the curve, so the shape can never surprise you.

How do you join Bézier curves smoothly?

Two segments meet continuously (C⁰) if they share an endpoint. For a smooth tangent (G¹) the control point before the joint, the shared point, and the control point after the joint must be collinear — the two handles point in opposite directions along one line. Making those handle lengths equal upgrades the join to C¹. Chained this way, the pieces form a Bézier spline.

Can a Bézier curve draw a perfect circle?

No — a polynomial Bézier cannot represent a circular arc exactly, only approximate one (a common cubic approximation of a quarter-circle sets the handle length to about 0.5523 times the radius, with error under ~0.03%). Exact circles need rational Béziers / NURBS, where control-point weights let ratios of polynomials reproduce conics precisely.