I wrote a function called deBoor
using the Cox-de Boor algorithm to generate a B-spline curve.
(*Search the index of span [ui,ui+1)*)
searchSpan[knots_, u0_] :=
With[{max = Max[knots]},
If[u0 == max,
Position[knots, max][[1, 1]] - 2,
Ordering[UnitStep[u0 - knots], 1][[1]] - 2]
]
(*The definition of α coefficient*)
α[{deg_, knots_}, {j_, k_}, u0_] /;
knots[[j + deg + 2]] == knots[[j + k + 1]] := 0
α[{deg_, knots_}, {j_, k_}, u0_] :=
(u0 - knots[[j + k + 1]])/(knots[[j + deg + 2]] - knots[[j + k + 1]])
(*Implementation of de Boor algorithm*)
deBoor[pts : {{_, _} ..}, {deg_, knots_}, u0_] :=
Module[{calcNextGroup, idx = searchSpan[knots, u0]},
calcNextGroup =
Function[{points, k},
Module[{coords, coeffs},
coords = Partition[points, 2, 1];
coeffs = {1 - #, #} & /@ (α[{deg, knots}, {#, k + 1}, u0] & /@
Range[idx - deg, idx - k - 1]);
{Plus @@@ MapThread[Times, {coords, coeffs}], k + 1}]
];
Nest[calcNextGroup[Sequence @@ #] &,
{pts[[idx - deg + 1 ;; idx + 1]], 0}, deg][[1, 1]]
]
TEST
points =
{{1, 4}, {.5, 6}, {5, 4}, {3, 12}, {11, 14}, {8, 4}, {12, 3}, {11, 9}, {15, 10}, {17, 8}};
(*here, I set the knots uniformly*)
knots = {0, 0, 0, 0, 1/7, 2/7, 3/7, 4/7, 5/7, 6/7, 1, 1, 1, 1};
ParametricPlot[
deBoor[points, {3, knots}, t], {t, 0, 1}, Axes -> False]
Now, I need to close this curve. My first thought is append the first point to the pts
list.
pointsCLOSE =
{{1, 4}, {.5, 6}, {5, 4}, {3, 12}, {11, 14}, {8, 4}, {12, 3},
{11, 9}, {15, 10}, {17, 8}, {1, 4}};
(*here, I set the knots uniformly*)
knotsCLOSE = {0, 0, 0, 0, 1/8, 2/8, 3/8, 4/8, 5/8, 6/8, 7/8, 1, 1, 1, 1};
ParametricPlot[
deBoor[pointsCLOSE, {3, knotsCLOSE}, t], {t, 0, 1}, Axes -> False]
However, the built-in BSplineCurve
gives a different curve
Graphics[{BSplineCurve[points, SplineClosed -> True]}]
The comparison of two graphics
So my thought is wrong
In the chat room, thanks to halirutan's suggestion
For this closed form, you need to assume the endpoints to be periodic. It is not enough to just pre-/append one point.
QUESTION
What does the the endpoints to be periodic mean? I didn't learn it from The NURBS Book
How to generate a closed B-spline curve like the built-in
BSplineCurve[pts, SplineClosed -> True]
?
UPDATE
uniformKnots[pts_, deg_] :=
With[{n = Length@pts},
Join[
ConstantArray[0, deg + 1],
Range[1, n - deg - 1]/(n - deg),
ConstantArray[1, deg + 1]]
]
Manipulate[
With[{pts = Join[points, points[[1 ;; n]]]},
ParametricPlot[
deBoor[pts, {3, uniformKnots[pts, 3]}, t], {t, 0, 1},
Axes -> False]], {n, 1, 10, 1}
]
- I didn't how many points should I append to the original points list?
PeriodicInterpolation
forInterpolation
. $\endgroup$pts list
. Namely,pointsCLOSE1 = {{1, 4}, {.5, 6}, {5, 4}, {3, 12}, {11, 14}, {8, 4}, {12, 3}, {11, 9}, {15, 10}, {17, 8}, {1, 4}, {.5, 6}, {5, 4}, {3, 12}, {11, 14}, {8, 4}, {12, 3}, {11, 9}, {15, 10}, {17, 8}}; knotsCLOSE1 = {0, 0, 0, 0, 1/17, 2/17, 3/17, 4/17, 5/17, 6/17, 7/17, 8/17, 9/17, 10/17, 11/17, 12/17, 13/17, 14/17, 15/17, 16/17, 1, 1, 1, 1};ParametricPlot[deBoor[pointsCLOSE1, {3, knotsCLOSE1}, t], {t, 0, 1}, Axes -> False]
$\endgroup$how many
points did I need to add? THX:) $\endgroup$knots
sequence own this style $\{u_0, u_1,\cdots,u_m\}$,points
own the style $\{P_0,P_1,\cdots,P_n\}$. In addtion thedegree
of B-spline curve is $p$, so they own the following relationship $$n+1+p=m$$ In general, the knots is uniform. $\endgroup$