Previous Up Next

17.2.3  B-splines

Finding B-splines from control points.

The command bspline finds a B-spline with a given list of control points and, optionally, a list of breakpoints.

Example

To define a sequence of control points, enter:

c:=2i,1-2i,5-i,6-4i,8+2i,5+i:;

Now compute the B-spline defined by the above points and uniform knots, with parameter t∈[0,1]:

bs:=bspline([c],t)
     









99 t3
2
+27 t2+9 t
567 t3
4
+
243 t2
2
−36 t+2
63 t3
2
−54 t2+36 t−3
297 t3
4
189 t2
2
+36 t−6
−117 t3+243 t2−162 t+41−162 t3+378 t2−279 t+64









          

To plot the result with alternating red-blue color for spline pieces and green control points, enter:

polygon(c,open); plotparam(bs[0],t=0..1/3,display=red+line_width_2); plotparam(bs[1],t=1/3..2/3,display=blue+line_width_2); plotparam(bs[2],t=2/3..1,display=red+line_width_2); point(c,display=point_point+point_width_3+green);

Sometimes it is useful to return the result in a piecewise form. Enter:

bs:=bspline([c],t,piecewise)
     




















99
2
 t3+27 t2+9 t,
t≥ 0∧ 
1
3
>t
63
2
 t3−54 t2+36 t−3,
2
3
>t
−117 t3+243 t2−162 t+41,1≥ t
,










567
4
 t3+
243
2
 t2−36 t+2,
t≥ 0∧ 
1
3
>t
297
4
 t3
189
2
 t2+36 t−6,
2
3
>t
−162 t3+378 t2−279 t+64,1≥ t










          

The result is a list of components of the spline function. Now, for example, the command line

plotparam(bs,t=0..1)

draws the entire spline.

Fitting B-splines to data.

The fitspline command fits B-splines to (multidimensional) time-stamped data in the least-squares sense.

Examples

To generate some synthetic data with noise, enter:

x:=linspace(0,15,200):; y:=apply(t->cos(t)*exp(-0.1*t)*(1+randnorm(0,0.1)),x):;

The following command line computes y-values of a B-spline fit:

ys:=fitspline(tran([x,y]),x)]):;

Essentially, ys is the result of “snapping” y to a smooth curve. Now visualize the result by entering:

scatterplot(x,y,color=blue); listplot(tran([x,ys]))

You can use B-spline to trace a sequence of points in time. For example, generate a list of 2D locations by entering:

t:=linspace(0,10,50):; x:=apply(u->(u^2*sin(u)+u-1)/(1+u*sqrt(u))+randnorm(0,0.1),t):; y:=apply(u->(u^2*cos(u)-u+1)/(1+u*sqrt(u))+randnorm(0,0.1),t):;

The underlying smooth path of these “footsteps” can be approximated like this:

t1:=linspace(0,10,500):; listplot(fitspline(tran([t,x,y]),t1,20)),scatterplot(x,y,color=blue)

Such approximation is useful for estimating the total distance traveled or the velocity at a certain point in time, assuming that data represents a discretized trajectory of a moving object, such as e.g. a series of GPS positions would.

By setting the number of spline pieces (which is 20 in the above graph) to a value that is close to 50 (the number of samples), the resulting spline exhibits large oscillations near the beginning and end of the curve, reminiscent of Runge’s phenomenon:

listplot(fitspline(tran([t,x,y]),t1,45)),scatterplot(x,y,color=blue)

Warning: too many control points

Note that using Chebyshev nodes as breakpoints, which would be beneficial in the case of polynomial interpolation, does not make much difference here.


Previous Up Next