Curvature

After Steven Wittens, acko.net

Studied 2026-08-192D canvas. Exact analytic Bezier derivatives, one-dimensional bisection. No libraries.

Every pen tool in every drawing program keeps a node's two handles symmetric: equal length, opposite direction. That guarantees the tangent is continuous, so nothing kinks, and the result reads as smooth. It is not smooth. Curvature jumps at the join, and a curvature comb — a hair drawn along the normal, scaled by signed curvature — makes the jump visible in about a second. These figures build the comb out of the exact derivatives, then put a step in it, then remove the step with a one-dimensional root find.

1 · The curve

A cubic Bézier is a triple interpolation. Drag the four control points; move t and watch de Casteljau collapse three segments into two, two into one, one into the point on the curve. The last segment is the tangent direction.

Read this: the point on the curve is not the point on the hull, and it does not move at a constant rate. Equal steps in t are not equal steps in distance — figure 3 is that fact drawn as a graph.

2 · The comb

At each sample, take the exact first and second derivatives, form the signed curvature κ = (x′y″ − y′x″) / (x′² + y′²)^1.5, and draw a hair along the left normal of length κ·scale. The hairs are scaffolding. The envelope joining their tips is what the eye reads.

κ > 0κ < 0
Read this: the comb flips to the other side of the curve exactly at the inflection, where κ passes through zero. Drag a handle until it is nearly on top of its endpoint: |B′| → 0, κ blows up, and the hairs hit the drawing clamp. That singularity is real, not a bug in the plot.

3 · κ and speed, on one t axis

Both graphs are live while you drag figure 1 or 2. κ(t) is the comb, unrolled. |B′(t)| is the parametric speed — how fast the point moves per unit t, which for a Bézier is never constant.

κ > 0κ < 0|B′|
Read this: a Bézier is not arc-length parametrised. The speed graph sags in the middle of a curve with long handles and spikes where they are short, so an object animated on raw t visibly slows down and speeds up along a path that looks perfectly even. Every "constant speed along a path" routine exists because of this graph.

4 · The join

Two cubics sharing an endpoint. The switch controls what happens to the two handles either side of the join: corner leaves them free, symmetric is the pen-tool default, proportional scales the lengths by the two chord lengths,matched solves for curvature agreement. One comb and one κ graph run across both segments.

Read this: in symmetric mode the curve has no kink and the comb still steps at the join. That step is the whole article. Proportional usually makes it smaller and never makes it zero — it is a heuristic about handle length, and curvature is not a fact about handle length alone. Only matched closes it. Drift wobbles the far handle of the first segment so you can watch the mismatch breathe.

5 · The solve

Hold the join tangent direction fixed and let the outgoing handle length L be the only unknown. Then κ⁺ depends on L alone, and matching curvature is a root find in one variable.Bisection on f(L) = κ⁺(L) − κ⁻, with κ from the analytic derivatives, not from finite differences.

Read this: κ⁺(L) is a hyperbola — with the far handle held still it falls off as 1/L² — and κ⁻ is a horizontal line. Where they cross is the G2 handle length. Wind Lmax down until the crossing leaves the window and the readout says clamped: there is no honest answer inside the range, so the figure says so instead of inventing one. Sign mismatch has no solution at any length, because a longer handle cannot make a curve bend the other way.
A study after Steven Wittens, Curvature Beziers (acko.net). He is not the first person to point out that symmetric handles are not curvature continuous; he made the point unusually well, with the combs to prove it. This is our own rebuild of the parts that teach the most, not a reproduction of his page — in particular his exact quartic solve for a G2 join is replaced here by a one-dimensional root find on a single handle length, which is less general and much easier to trust.

What it actually does

  • Signed curvature is one line of arithmetic from the exact first and second derivatives, and the comb flips to the other side of the curve exactly at an inflection, where curvature passes through zero.
  • The hairs are scaffolding. The envelope joining their tips is what the eye actually reads, and a comb without it is much harder to interpret.
  • Parametric speed deserves its own graph. Equal steps in t are nowhere near equal steps in distance, which is the same fact as the point on the curve lagging the point on the hull.
  • In symmetric mode the join has no kink and the curvature graph still shows a clean step. Proportional handles usually shrink that step and never reach zero, because curvature is not a fact about handle length alone.
  • Holding the tangent direction fixed leaves the outgoing handle length as the only unknown, and curvature at the join falls off as one over length squared. Matching it is a root find in one variable.

What the rebuild taught

  • Symmetry is a proxy for smoothness, not a definition of it. The whole argument fits in one figure once the comb is drawn, which is why the comb is the primitive worth keeping and the quartic is not.
  • Solve for what the user wants and hide the parameter. A handle whose length means radius of curvature is a better control than a handle whose length means nothing in particular.
  • A one-dimensional bisection on the analytic function is honest and robust. It also fails cleanly: sign mismatch has no solution at any length, because a longer handle cannot make a curve bend the other way, and saying "clamped" beats inventing an answer.
  • Take the derivatives analytically. Finite differences are fine until a handle length approaches zero, where speed goes to zero and curvature blows up, and then the plot is measuring the differencing rather than the curve.
  • The payoff figure has to have a payoff by default. The first join geometry was an elegant S, two segments bending opposite ways, which makes the most dramatic comb picture because the comb flips sides at the join. It also has no G2 solution at any handle length, so the solve figure sat there permanently reporting failure. Choosing a default for one figure without checking what it does to the next one is the whole mistake.
  • The root find turned out not to be doing real work. With the far handle held still, curvature at the join is exactly C over L squared, so there is a closed form. The solver stayed because it only ever calls the curvature function and so remains honest if the far handle is later tied to L, but the thing that actually teaches is the plot: a hyperbola crossing a line reads instantly in a way that "23 iterations" never will.
  • Uniform scale is not negotiable when the subject is curvature, so the world aspect has to be chosen to match the canvas aspect rather than to a comfortable round number. A 1000 by 560 world on a 2.7:1 canvas letterboxes every figure with dead margin.

Rebuild

Five figures: the curve with de Casteljau, the comb, the two graphs on a shared t axis, the join with four handle modes, and the solve drawn as a function of handle length with the crossing marked. The singularity at zero handle length is left visible rather than hidden.

Primitives

Curvature combSigned curvature drawn as hairs along the normal. Makes a discontinuity visible that no amount of staring at the curve will show.
Solve, not exposeGive the user the outcome they care about and solve for the parameter underneath. Turns a handle into a result.
SubdivisionRecursive splitting with the endpoints held fixed. Detail on demand, from de Casteljau to a coastline.

The work it is after

acko.net/blog/curvature-beziers