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$
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$
  • $\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 '14 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 '14 at 8:28
  • $\begingroup$ Dear ubpdqn, That's all right,it's my pleasure to learn from your solution.:-) $\endgroup$ – xyz Sep 30 '14 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 '14 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$
  • $\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 '14 at 12:50
  • 1
    $\begingroup$ n = Length@pts NOTE: pts not opts $\endgroup$ – Bob Hanlon Sep 29 '14 at 14:47
  • $\begingroup$ @BobHanlon, Ok, thanks :-) $\endgroup$ – xyz Sep 30 '14 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.