Internally, Easel represents many types of 2D shapes using Bézier paths and performs many operations on these curves as you work on your project. One frequent operation is calculating the bounding box of a path – and we recently sped up this calculation tenfold.

Easel used to do this by taking the path…

a path

…then sampling a bunch of points on it…

sampled points

…and then looking at all of those points to find the min and max X and Y values:

sample extrema

We were unhappy with this for two reasons:

  1. The result was an approximation limited by the number of samples.
  2. For complex paths, it required calculating many thousands of sampled points – so it was slow.

To build a faster solution, we went back to the underlying Bézier path representation, which is a series of cubic Bézier curves, each defined by two endpoints (endpoints) with two control points (control points) in between:

path with handles

Between each pair of endpoints, the X and Y values are defined by parametric equations with polynomial coefficients determined by the endpoints and and control points and :

Some high school calculus lets us know any points where the X (curve x extrema) or Y (curve y extrema) derivatives are zero – which is where those functions have their minimum and maximum values:

path with handles and curve extrema

Those points, and the original endpoints, are the only points we need to consider to find the bounding box for the path:

path with handles and curve extrema

And not only is it the precise bounding box, but we found it while evaluating far fewer points!

precise bounding box