12
$\begingroup$

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.

$\endgroup$
  • $\begingroup$ Why do you insist on BezierCurve instead of Interpolation? $\endgroup$ – Szabolcs Sep 5 '16 at 10:53
  • $\begingroup$ What is your code? Because BezierCurve[pts] doesn't go through these four points. $\endgroup$ – Feyre Sep 5 '16 at 11:06
  • $\begingroup$ 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. $\endgroup$ – Bob Ueland Sep 5 '16 at 11:06
11
$\begingroup$

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]}]

Bézier

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}}]

comparison

$\endgroup$
  • $\begingroup$ Is the slight difference with Interpolation[] expected? $\endgroup$ – Feyre Sep 5 '16 at 11:13
  • 5
    $\begingroup$ @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. $\endgroup$ – xyz Sep 5 '16 at 11:20
  • 1
    $\begingroup$ 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. $\endgroup$ – george2079 Sep 5 '16 at 12:25
  • 1
    $\begingroup$ The difference is only because you used chord length instead of the abscissas in setting up the linear system for the control points. $\endgroup$ – J. M. is away Sep 3 '17 at 5:40
  • 1
    $\begingroup$ @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". $\endgroup$ – andre314 Apr 1 '18 at 22:18
5
$\begingroup$

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]}}]

interpolating Bézier curve

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]]

BezierCurve vs. InterpolatingFunction

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

difference

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.