At the end of this post I define a function to do this. It works for all combinations of option settings except where SplineClosed->True
and SplineKnots->list
, since I don't know how to reproduce the built-in option settings in that case. Example:
spline = BSplineCurve[{{1,0}, {1,1}, {0,1}, {-1,1}}, SplineClosed->True];
FullBSplineCurve @ spline
BSplineCurve[{{1, 0}, {1, 1}, {0, 1}, {-1, 1}, {1, 0}, {1, 1}, {0, 1}},
SplineDegree -> 3, SplineClosed -> False,
SplineKnots -> {0, 1/10, 1/5, 3/10, 2/5, 1/2, 3/5, 7/10, 4/5, 9/10, 1},
SplineWeights -> {1, 1, 1, 1, 1, 1, 1}]
Check:
Graphics[{
Opacity[.5],
Red, spline,
Blue, FullBSplineCurve @ spline
}]
Notice how the color is purple, indicating that the original spline and the FullBSplineCurve
version overlap.
Here is the code:
FullBSplineCurve[b:BSplineCurve[pts_, OptionsPattern[]]] := Module[{p, k, w, d, c},
{k, w, d, c} = OptionValue[BSplineCurve, {SplineKnots, SplineWeights, SplineDegree, SplineClosed}];
If[ListQ @ k && c === True,
Message[FullBSplineCurve::unsup];
Return[b]
];
d = If[ListQ @ k,
Length[k] - Length[pts] - 1,
Min[Length[pts] - 1, Replace[d, Except[_Integer?Positive] -> 3]]
];
w = Replace[w, Except[_List] -> ConstantArray[1, Length[pts]]];
If[TrueQ @ c,
Switch[k,
"Unclamped" | Automatic,
k = Subdivide[0, 1, Length[pts] + 2d];
p = Join[pts, pts[[;;d]]];
w = Join[w, w[[;;d]]],
"Clamped",
k = ArrayPad[Subdivide[0, 1, Length[pts]-d+1], d, "Fixed"];
p = Append[pts, First @ pts];
w = Append[w, First @ w]
],
p = pts;
Switch[k,
"Clamped" | Automatic,
k = ArrayPad[Subdivide[0, 1, Length[pts]-d], d, "Fixed"],
"Unclamped",
k = Subdivide[0, 1, Length[pts] + d]
]
];
BSplineCurve[p, SplineDegree->d, SplineClosed->False, SplineKnots->k, SplineWeights->w]
]
FullBSplineCurve::unsup = "Closed curves with a list knot specification are not supported";