9
$\begingroup$

In general, the $nth$-degree Bézier curve is defined as: $$\vec{C}(u)=\sum_{i=0}^{n} B_{i,n}(u) \vec{P_i} \qquad 0\leq u\leq1$$

where $B_{i,n}(u)$ is the classical Bernstein polynomial, $$B_{i,n}(u)=\frac{n!}{i!(n-i)!}u^i(1-u)^{n-i}$$

$\vec{P_i}$ is the control point.

I have written a function to plot these curves:

Trial 1

bezierPlot1[n_, pts : {{_, _} ..}, opts : OptionsPattern[Plot]]:=
 ParametricPlot[
  Total@Table[
   BernsteinBasis[n, i, u] # & /@ pts, {i, 0, n}], {u, 0, 1}]

pts = {{0, 0}, {2, 4}, {4, 5}, {6, 0}};
bezierPlot1[3,pts]

It failed; that is, no graphics appeared.

Trial 2

I replaced the built-in function BernsteinBasis with $\frac{n!}{i! (n - i)!} u^i(1 - u)^{n - i}$

 bezierPlot2[n_, pts : {{_, _} ..}, u_, opts : OptionsPattern[Plot]] :=
  ParametricPlot[
   Total@Table[
     n!/(i! (n - i)!) u^i (1 - u)^(n - i) # & /@ pts, {i, 0, n}] /. 
    u -> x, {x, 0, 1}]

 bezierPlot2[3, pts, u]

It failed

Lastly, I know that Mathematica has the built-in function BezierCurve:

Graphics[{BezierCurve[pts], Green, Line[pts], Red, Point[pts]}]

Bézier curve

So my question is, how do I make my bezierPlot work normally?

$\endgroup$

3 Answers 3

12
$\begingroup$
f[n_, j_, u_] := PiecewiseExpand[BernsteinBasis[n, j, u]]
cv[pt_, n_, u_] := (f[n, #, u] & /@ Range[0, n]).pt

Test:

pts = {{0, 0}, {2, 4}, {4, 5}, {6, 0}};
ParametricPlot[cv[pts, Length@pts - 1, v], {v, 0, 1}, 
 Epilog -> {Red, PointSize[0.02], Point[pts], Green, Line[pts]}, 
 PlotRange -> {0, 6}]

enter image description here

Or

DynamicModule[{p = {{0, 0}, {2, 4}, {4, 5}, {6, 0}}},
 LocatorPane[Dynamic[p], Dynamic@
   ParametricPlot[cv[p, Length@p - 1, v], {v, 0, 1}, 
    Epilog -> {Red, PointSize[0.02], Point[p], Green, Line[p]}, 
    PlotRange -> {0, 6}], Appearance -> None]]

enter image description here

To plot:

bezplot[pt_, opts : OptionsPattern[Plot]] := 
 ParametricPlot[cv[pt, Length@pt - 1, x], {x, 0, 1}, 
  Epilog -> {Red, PointSize[0.02], Point[pt], Green, Line[pt]}, opts]

So,

bezplot[pts, PlotRange -> {0, 6}]

yields the first figure

$\endgroup$
4
  • $\begingroup$ +1, Thanks very much. BTW, could you tell me why does my method cannot work. I'd like know which reason lead to the failture and I will avoid this mistake next time. :-) $\endgroup$
    – xyz
    Sep 29, 2014 at 13:07
  • $\begingroup$ @Tangshutao apologies for delay in replying (timezone issue)...you seem to have solved yourself with your answer $\endgroup$
    – ubpdqn
    Sep 30, 2014 at 8:28
  • $\begingroup$ Dear ubpdqn, That's all right,it's my pleasure to learn from your solution.:-) $\endgroup$
    – xyz
    Sep 30, 2014 at 9:32
  • $\begingroup$ Hi, @ubpdqn, today, I discovered a difference between BezierCurve and our functions bezplot & bezierPlot, pts = {{0, 0}, {2, 4}, {4, 5}, {5, 5}, {6, 0}}; Graphics[{BezierCurve[pts], Green, Line[pts], Red, Point[pts]}] seemed give the wrong result in V8 and V9.Do you think is it a bug? $\endgroup$
    – xyz
    Oct 1, 2014 at 10:28
4
$\begingroup$

I believe ...

bezierPlot1[n_, pts : {{_, _} ..}, opts : OptionsPattern[Plot]] := 
 ParametricPlot[ Sum[BernsteinBasis[n - 1, i, u] pts[[i + 1]], {i, 0, n - 1}], {u, 0, 1}, opts]

pts = {{0, 0}, {2, 1}, {4, 3}, {6, 2}};
bezierPlot1[4, pts,  Epilog -> {Green, Line@pts, PointSize[Medium], Red, Point@pts}, 
                                PlotRange -> Evaluate[{Min @@ #, Max @@ #} & /@ Transpose@pts]]

Mathematica graphics

$\endgroup$
3
  • $\begingroup$ Dear belisarius, If I omit the n, namely, bezierPlot[pts : {{_, _} ..}, opts : OptionsPattern[Plot]] := Module[{n = Length@opts}, Show[ {ParametricPlot[ Sum[ BernsteinBasis[n - 1, i, u] pts[[i + 1]], {i, 0, n - 1}], {u, 0, 1}], Graphics[{Green, Line[pts], Red, Point[pts]}]}, opts] ] it will lost the Besier curve, Could you tell me? I alway confused when I encounter the condition.Thanks $\endgroup$
    – xyz
    Sep 29, 2014 at 12:50
  • 1
    $\begingroup$ n = Length@pts NOTE: pts not opts $\endgroup$
    – Bob Hanlon
    Sep 29, 2014 at 14:47
  • $\begingroup$ @BobHanlon, Ok, thanks :-) $\endgroup$
    – xyz
    Sep 30, 2014 at 1:52
2
$\begingroup$

Review

Table[BernsteinBasis[n, i, u] # & /@ pts, {i, 0, n}] was the main problem.

Revising

I use the MapIndexed to fill in the second argument in BernsteinBasis[n, i, u]

 bezierPlot[n_, pts : {{_, _} ..}, opts : OptionsPattern[Plot]] :=
  ParametricPlot[
   Total@MapIndexed[
    BernsteinBasis[n, First@#2 - 1, u] #1 &, pts], {u, 0, 1}, 
     Epilog -> {Red, PointSize[0.02], Point[pts], Green, Line[pts]}, opts]

Test

pts={{0, 0}, {2, 4}, {4, 5}, {6, 0}};
bezierPlot[3, pts, PlotRange -> {{0, 8}, {0, 6}}]

enter image description here

Edit

bezierPlotSuper[n_, pts : {{_, _} ..}, opts : OptionsPattern[Plot]] :=
 ParametricPlot[
  Total@MapIndexed[
   BernsteinBasis[n, First@#2 - 1, u] #1 &, pts], {u, 0, 1},
    Epilog -> Join[
      Text @@@ (Thread@{Table[Style[Subscript["P", i], 14], {i, 0, n}],
        # + {.4, .2} & /@ pts}), 
      {Red, PointSize[0.01], Point[pts], Green, Line[pts]}], opts]

Test

bezierPlotSuper[3, {{2, 0}, {3, 4}, {4, 5}, {7, 8}}, 
  PlotRange -> {{-1, 11}, {-1,11}}]

enter image description here

$\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.