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

2 Answers 2

13
$\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$
7
  • $\begingroup$ Is the slight difference with Interpolation[] expected? $\endgroup$
    – Feyre
    Sep 5, 2016 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, 2016 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, 2016 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$ Sep 3, 2017 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, 2018 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 and acknowledge you have read our privacy policy.

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