# How to calculate the control points of a Bézier curve?

To plot a BezierCurve in Mathematica, I need control points. But, I do not know the control points; I only know the points through which the Bézier curve passes. Take a simple example:

A Bézier curve goes through the 4 points (0,0), (2,1), (4,3) and (6,1). Find the two control points.

How would I go about finding the two control points in this example? The solution of this simple example will give me a clue on how to solve the general case.

• Why do you insist on BezierCurve instead of Interpolation? – Szabolcs Sep 5 '16 at 10:53
• What is your code? Because BezierCurve[pts] doesn't go through these four points. – Feyre Sep 5 '16 at 11:06
• Because what I really want to do is to draw a Bezier curve containing hundred of points. I know the points that the curve passes through but in order to plot it I need the control points instead. If I can do it for a simple case of 4 points I will figure out how to do it for hundred of points. – Bob Ueland Sep 5 '16 at 11:06

Here is my approach:

pts = {{0, 0}, {2, 1}, {4, 3}, {6, 1}};
paras = FoldList[Plus, 0, Normalize[(Norm /@ Differences[pts]), Total]] // N
mat = Outer[BernsteinBasis[3, #1, #2] &, Range[0, 3], paras] // Transpose;
ctrlpts = LinearSolve[mat, pts]
(* {{0., 0.}, {2.71043, -0.262717}, {3.94236, 6.32778}, {6., 1.}} *)

Graphics[{BezierCurve[ctrlpts], PointSize[Medium], Red, Point[pts]}]


### Comparison with Interpolation[]

To show that the results of the Bézier curve interpolant and the built-in Interpolation[] are vastly different, I will use the following data:

pts1 = {{-1, 0}, {2, 1}, {4, 4}, {6, -3}};
mat1 = Outer[BernsteinBasis[3, #1, #2] &, Range[0, 3],
FoldList[Plus, 0.0,
Normalize[(Norm /@ Differences[pts1]), Total]]] // Transpose;

f = Interpolation[pts1];
Show[Plot[f[x], {x, -1, 6}],
Graphics[{BezierCurve[LinearSolve[mat1, pts1]],
PointSize[Medium], Red, Point[pts1]}],
PlotRange -> {Automatic, {-3, 6}}]


• Is the slight difference with Interpolation[] expected? – Feyre Sep 5 '16 at 11:13
• @Feyre Of course, they use the different algorithms(basis function). I think the Interpolation[] uses the classical Largrange interpolation strategy, while for the Bezier curve, it uses the Bernstein basis. – xyz Sep 5 '16 at 11:20
• I'm sure you could find an example where the Interpolation result is vastly different. It might be worthwhile to show the comparison in the answer. – george2079 Sep 5 '16 at 12:25
• The difference is only because you used chord length instead of the abscissas in setting up the linear system for the control points. – J. M.'s torpor Sep 3 '17 at 5:40
• @J.M. is right : the visual difference between the 2 curves disappears when one replace FoldList[balh blah blah ...] by Rescale[First /@ pts1] in the code above. Nevertheless it is possible that the curves are mathematically different, for example because the default method used by Interpolation is "Hermite" instead of "Spline". – andre314 Apr 1 '18 at 22:18

There's no need to resort to chord length parametrization as was done in the other answer for this simple interpolation problem.

pts = {{0, 0}, {2, 1}, {4, 3}, {6, 1}};
{xt, yt} = Transpose[pts];
cp = LinearSolve[Outer[BernsteinBasis[3, #2, #1] &, Rescale[xt], Range[0, 3]], yt]
{0, -7/6, 20/3, 1}

Graphics[{{Directive[AbsoluteThickness[2], ColorData[97, 1]],
BezierCurve[Transpose[{xt, cp}]]},
{Directive[AbsolutePointSize[6], ColorData[97, 2]], Point[pts]}}]


An explanation for the following two results is left as an exercise for the interested reader:

if = Interpolation[pts];
Plot[if[x], {x, 0, 6},
Epilog -> {Directive[AbsoluteThickness[2], ColorData[97, 2]],
BezierCurve[Transpose[{xt, cp}]]},
PlotStyle -> AbsoluteThickness[6]]


Plot[if[x] - cp.BernsteinBasis[3, Range[0, 3], Rescale[x, MinMax[xt]]],
{x, 0, 6}, Evaluated -> True, PlotRange -> All]