I implemented the Bezier curve like built-in BezierCurve
as follow:
SplineDegree -> d
specifies that the underlying polynomial basis should have maximal degreed
.
Method
is a option that determining which algorithm was used.
ControlPoints
is a option that determining whether show the control points
SplineClosed
is an option that specifies whether spline curves or surfaces should be closed.
CAGDBezierCurve
by default represents a composite cubic Bézier curve.With
SplineDegree -> d
,CAGDBezierCurve
withd + 1
control points yields a simple degree -d
Bézier curve.With fewer control points, a lower - degree curve is generated. With more control points, a composite Bézier curve is generated.
UPDATE for 3D CASE
Options[CAGDBezierCurve] = {SplineClosed -> False,
SplineDegree -> Automatic, ControlPoints -> False, Method -> Automatic};
CAGDBezierCurve[pts : {{_, _} ..} | {{_, _, _} ..}, opts : OptionsPattern[]] :=
Module[{sc, sd, cp, Bezier, ptgroup},
sc = OptionValue[SplineClosed];
sd = OptionValue[SplineDegree] /. Automatic -> 3;
cp = OptionValue[ControlPoints];
Bezier =
ToExpression@OptionValue[Method] /. Automatic -> BezierDefinition;
ptgroup = Partition[pts, sd + 1, sd, 1, {}];
If[Length@First@pts == 2,
ParametricPlot[
Evaluate[Bezier[#, u] & /@ ptgroup], {u, 0, 1},
Evaluate@
(Sequence @@
FilterRules[{opts}, Options[ParametricPlot]]),
Axes -> False, PlotRange -> All,
Epilog -> If[cp, {Green, Line[pts], Red, Point[pts]}, {}]],
Show[
{ParametricPlot3D[
Evaluate[Bezier[#, u] & /@ ptgroup], {u, 0, 1},
Evaluate@
(Sequence @@FilterRules[{opts}, Options[ParametricPlot3D]]),
Axes -> False, PlotRange -> All],
Graphics3D[
If[cp, {Green, Line[pts], Red, Point[pts]}]]}]
]
]
BezierDefinition[pts_, u0_?NumericQ] :=
Nest[
MovingAverage[
ArrayPad[#, 1], {u0, 1 - u0}] &, {1}, Length[pts] - 1].pts
deCasteljau[pts_, u0_?NumericQ] :=
Nest[
MovingAverage[#, {1 - u0, u0}] &, pts, Length@pts - 1]
Owning to the HoldAll
attribute of ParametricPlot
, so I must used the Evaluate
three times in the ParametricPlot
.
In addition, I know the ParametricPlot
owns the Evaluated-> True
option, so I refactor(remove Evaluate
) the part of ParametricPlot
as below:
ParametricPlot[
Bezier[#, u] & /@ ptGroup, {u, 0, 1},
Evaluated -> True,
Sequence @@
FilterRules[{opts}, Options[ParametricPlot]],
Axes -> False, PlotRange -> All,
Epilog -> If[cp, {Green, Line[pts], Red, Point[pts]}, {}]
]
However, it failed.
TEST
pts = {{0, 0}, {1, 1}, {2, -1}, {3, 0}, {4, -2}, {5, 1}};
CAGDBezierCurve[pts, SplineDegree -> #1, SplineClosed -> #2,
ControlPoints -> True] & @@@ {{2, True}, {3, False}} // Row
Graphics[{Green, Line[pts], Red, Point[pts], Black,
BezierCurve[pts, SplineDegree -> #1,
SplineClosed -> #2]}] & @@@ {{2, True}, {3, False}} // Row
pts1 = {{0, 0, 0}, {1, 1, 1}, {2, -1, 1}, {3, 0, 2}, {5, 3, 4}};
CAGDBezierCurve[pts1, SplineDegree -> 4, ControlPoints -> True]
QUESTION
Is there a solution to deal with avoiding using
Evaluate
function many times?Why the
PlotRange -> All
cannot show the entire graph?
ParametricPlot @@ {args...}
, orBlock[{u}, ParametricPlot @@ {args...}]
, to get aroundEvaluated
. $\endgroup$ParametricPlot @@ {args...}
,the args
would be evalauted firstly.THX:) $\endgroup$