Lab

Fitting Béziers

Draw on the canvas. Each stroke is fitted, live, with Philip J. Schneider’s algorithm from Graphics Gems (1990): a chain of cubic Béziers that stays within a tolerance of the ink.

0 strokes

Draw on this canvas to fit cubic Bézier curves to a freehand stroke. A browser with canvas support is required.

Drag to draw · tolerance is the farthest a point may sit from the curve · Ctrl or ⌘ Z undoes

How it works

The fitter is Philip J. Schneider, “An Algorithm for Automatically Fitting Digitized Curves,” Graphics Gems (Academic Press, 1990). A freehand stroke becomes a chain of cubic Béziers that stay within the tolerance of every point, with matching tangents at each join.

  1. End tangents. The curve leaves along the chord from the first point to the second, and arrives along the chord from the last point back toward the one before it. Handles may only scale along those directions.
  2. Chord-length time. Each point gets a parameter from 0 to 1 by how far it sits along the polyline.
  3. Least squares. Endpoints and handle directions are fixed, so only the two handle lengths are unknown. Minimizing squared error gives a 2×2 system. A negative or tiny length falls back to one third of the chord.
  4. Worst point. If every point lies within the tolerance of the curve at its parameter, the segment is kept.
  5. Newton step. When the miss is less than four times the tolerance, each parameter is nudged toward the nearest spot on the curve and the fit is tried again.
  6. Split. Still too far, and the stroke is cut at the worst point. Both halves share one tangent there, so the join stays smooth. A sharp corner becomes many short segments instead of a real corner.

Lower the tolerance and the fit uses more segments that hug the ink. Raise it and the same stroke becomes fewer, smoother cubics. Min point spacing thins the samples a slow hand leaves bunched together.

Back to Lab