rov14_6.mws

Chapter 14. Spline Curves

> restart:

14.1 Preliminary Facts and Examples

Example.

1.

> r1:=[4*t,4*t]: r2:=[1+t,1+t]: t1:=0: t2:=1/4: t3:=0: t4:=1:

> p1:=plot([r1[1],r1[2],t=t1..t2]): p2:=plot([r2[1],r2[2],t=t3..t4]):

> c1:=plottools[circle](subs(t=t2, r1), 0.02):

> plots[display]([p1, p2, c1], scaling=constrained);

>

2.

> r1:=[-(1-t)^2, (1-t)^2]: t1:=0: t2:=1: r2:=[t^2, t^2]: t3:=0: t4:=1:

> p1:=plot([r1[1], r1[2], t=t1..t2]): p2:=plot([r2[1], r2[2], t=t3..t4]):

> c1:=plottools[circle](subs(t=t2, r1), 0.02):

> plots[display]([p1, p2, c1], scaling=constrained,axes=framed);

3.

> r1:=[sin(Pi/2*t^2),cos(Pi/2*t^2)]: t1:=0: t2:=1: r2:=[cos(Pi/2*t^2),-sin(Pi/2*t^2)]: t3:=0: t4:=1:

> p1:=plot([r1[1], r1[2], t=t1..t2]): p2:=plot([r2[1], r2[2], t=t3..t4]):

> c1:=plottools[circle](subs(t=t2, r1), 0.02):

> plots[display]([p1, p2, c1], scaling=constrained,axes=framed);

4.

> r1:=[cos(Pi/2*(1-t)^3),sin(Pi/2*(1-t)^3)]: t1:=0: t2:=1: r2:=[2-cos(Pi/2*t^3),-sin(Pi/2*t^3)]: t3:=0: t4:=1:

> p1:=plot([r1[1],r1[2],t=t1..t2]): p2:=plot([r2[1],r2[2],t=t3..t4]):

> c1:=plottools[circle](subs(t=t2, r1), 0.02):

> plots[display]([p1, p2, c1], scaling=constrained);

5.

> r1:=[t^2+t/2-3/2, -t^2+2*t]: t1:=0: t2:=1: r2:=[-t^2+5*t/2, -t^2+1]: t3:=0: t4:=1:

> p1:=plot([r1[1],r1[2],t=t1..t2]): p2:=plot([r2[1],r2[2],t=t3..t4]):

> c1:=plottools[circle](subs(t=t2, r1), 0.02):

> plots[display]([p1, p2, c1], scaling=constrained,axes=framed);

>

14.2 Composed Bezier Curves

14.2.1 Elementary Cubic Bezier Curve

> bez_2d := proc(xp, yp) local s,n,i,p,pp,m; n[0]:=t->(1-t)^3; n[1]:=t->3*t*(1-t)^2; n[2]:=t->3*t^2*(1-t); n[3]:=t->t^3; m:=nops(xp)/2; for s from 1 to 2*m do p[s-1]:=[xp[s], yp[s]] od; p[0]:=2*p[0]-p[1]; p[2*m-1]:=2*p[2*m-1]-p[2*m-2]; pp:=n[0](t-i+1)*(p[2*i-2]+p[2*i-1])/2+n[1](t-i+1)*p[2*i-1]+n[2](t-i+1)*p[2*i]+n[3](t-i+1)*(p[2*i]+p[2*i+1])/2; RETURN(evalm(sum((1+signum(-t+i))*(1+signum(t-i+1))/4*pp, i=1..m-1))) end:

Example 2 .

1. Plot the plane composed Bezier curve using the command bez_2d(xp, yp) .

> xp:=[.056, .287, .655, .716, .228, .269, .666, .929]: yp:=[.820, .202, .202, .521, .521, .820, .820, .227]:

> polygon:=plot([seq([xp[j], yp[j]], j=1..nops(xp))]):

> bez:=bez_2d(xp,yp): curve:=plot([bez[1],bez[2], t=0.001..nops(xp)/2-1.001]): plots[display]([curve, polygon]);

Continuation . We plot the self-repeating composed Bezier curve, where the circled points are derived by the program

> x1:=[op(xp),seq(seq(xp[i]+.61*j,i=3..nops(xp)),j=1..3)]; y1:=[op(yp),seq(seq(yp[i], i=3..nops(yp)),j=1..3)];

> P1:=plot([seq([x1[j], y1[j]], j=1..nops(x1))],scaling=constrained): %;

> bez1:=bez_2d(x1, y1): curve1:=plot([bez1[1], bez1[2], t=0.001..nops(x1)/2-1.001]): plots[display]([curve1, P1]);

3. Plot closed Bezier curves of two types:

(a) with the loop having a singular point, k in N.

> k:=3: xp:=[seq(sin(2*Pi*i/(2*k-1)), i=1..2*k)]: yp:=[seq(cos(2*Pi*i/(2*k-1)), i=1..2*k)]:

> polygon:=plot([seq([xp[j], yp[j]], j=1..nops(xp))]):

> bez:=bez_2d(xp, yp): curve:=plot([bez[1], bez[2], t=0.001..nops(xp)/2-1.001]): plots[display]([curve, polygon]);

(b)

> k:=3: xp:=[seq(cos(2*Pi*i/(2*k)), i=1..2*k+2)]: yp:=[seq(sin(2*Pi*i/(2*k)), i=1..2*k+2)]: xp[1]:=(xp[2]+xp[2*k+1])/2: yp[1]:=(yp[2]+yp[2*k+1])/2: xp[2*k+2]:=xp[1]: yp[2*k+2]:=yp[1]:

> polygon:=plot([seq([xp[j], yp[j]], j=1..nops(xp))]):

> bez:=bez_2d(xp,yp): curve:=plot([bez[1],bez[2], t=0.001..nops(xp)/2-1.001]): plots[display]([curve,polygon]);

14.3 Composed B -Spline Curves

Here is a procedure for deriving and plotting given data in the plane.

> bspl_2d := proc(xp,yp) local s,n,i,p,pp,m; n[0]:=t->(1-t)^3/6; n[1]:=t->(3*t^3-6*t^2+4)/6; n[2]:=t-> (-3*t^3+3*t^2+3*t+1)/6; n[3]:=t->t^3/6; m:=nops(xp)-1; for s from 1 to m+1 do p[s-1]:=[xp[s], yp[s]] od; p[-1]:=p[0]; p[m+1]:=p[m]; p[-2]:=p[0]; p[m+2]:=p[m]; pp:=n[0](t-i+1)*p[i-1]+n[1](t-i+1)*p[i]+n[2](t-i+1)*p[i+1]+n[3](t-i+1)*p[i+2]; RETURN(evalm(sum((1+signum(-t+i))*(1+signum(t-i+1))/4*pp,i=-1..m))) end:

Use the procedure bspl_2d(xp,yp) to plot the plane curve.

> xp:=[.056, .287, .655, .716, .228, .269, .666, .929]: yp:=[.820, .202, .202, .521, .521, .820, .820, .227]:

> polygon:=plot([seq([xp[j], yp[j]], j=1..nops(xp))]):

> bs:= bspl_2d(xp,yp): curve:=plot([bs[1], bs[2], t=-1.999..nops(xp)-1.001]): plots[display]([curve,polygon]);

P rocedure of deriving and plotting B-spline in .

> bspl_3d:=proc(xp,yp,zp) local n,i,s,pp,p; global spl,m,t; n[0]:=t->(1-t)^3/6; n[1]:=t->(3*t^3-6*t^2+4)/6; n[2]:=t->(-3*t^3+3*t^2+3*t+1)/6; n[3]:=t->t^3/6; m:=nops(xp)-1; for s from 1 to m+1 do p[s-1]:=[xp[s], yp[s], zp[s]] od; p[-1]:=p[0]; p[m+1]:=p[m]; p[-2]:=p[0]; p[m+2]:=p[m]; pp:=n[0](t-i+1)*p[i-1]+n[1](t-i+1)*p[i]+n[2](t-i+1)*p[i+1]+n[3](t-i+1)*p[i+2]; spl:=evalm(sum((1+signum(-t+i))*(1+signum(t-i+1))/4*pp, i=-1..m)); RETURN(plots[spacecurve](spl, t=-1.999..m-0.001)) end:

Use the procedure bspl_3d(xp, yp, zp) to plot the space curve.

> xp:=[.056, .287, .655, .716, .228, .269, .666, .929]: yp:=[.820, .202, .202, .521, .521, .820, .820, .227]: zp:=[1/4, 1/4, 0, 0, 0, 0, -1/4, -1/4]:

> polygon:=plots[pointplot3d]([seq([xp[j], yp[j], zp[j]], j=1..nops(xp))],symbol=circle): bs:=bspl_3d(xp,yp,zp):

> plots[display]([bs, polygon], scaling=constrained,axes=boxed);

Plot the knot trefolium

> xp:=[2, 0, -1, 0, 1, 0, -2, -1, 1, 2, 2]: yp:=[0, 0, 2, 4, 2, 0, 0, 2, 2, 0, 0]: zp:=[0, 1, 2, 2, 0, 2, 2, 1, 2, 1, 0]:

> bs:=bspl_3d(xp, yp, zp):%;

> plots[tubeplot]([spl[1], spl[2], spl[3], radius=.2], t=-2..nops(xp)-1, tubepoints=50, style=patchnogrid, color=[1, .8, .1], light=[75,50,1,.9,.5], ambientlight=[.4,.4,.4],axes=framed);

>

14.4 -Spline Curves

14.4.1 Examples of -Spline Curves

Procedure for deriving and plotting in .

> restart:

> beta_2d:=proc(xp,yp,beta1,beta2) local s,i,pp; global d,b1,b2,p,m,n; b1:=beta1; b2:=beta2; d:=evalf(2*b1^3+4*b1^2+4*b1+b2+2); m:=nops(xp)-1; n[0]:=t->2*b1^3*(1-t)^3/d; n[1]:=t->(2*b1^3*t*(t^2-3*t+3)+2*b1^2*(t^3-3*t^2+2)+2*b1*(t^3-3*t+2)+b2*(2*t^3-3*t^2+1))/d; n[2]:=t->(2*b1^2*t^2*(-t+3)+2*b1*t*(-t^2+3)+b2*t^2*(-2*t+3)+2*(-t^3+1))/d; n[3]:=t->2*t^3/d;for s from 1 to m+1 do p[s-1]:=[xp[s], yp[s]] od; p[-1]:=p[0]; p[m+1]:=p[m]; p[-2]:=p[0]; p[m+2]:=p[m]; pp:=n[0](t-i+1)*p[i-1]+n[1](t-i+1)*p[i]+n[2](t-i+1)*p[i+1]+n[3](t-i+1)*p[i+2]; RETURN(evalm(sum((1+signum(-t+i))*(1+signum(t-i+1))/4*pp,i=-1..m))) end:

Use the procedure beta_2d(xp,yp,zp) to plot the curve

> xp:=[.056, .287, .655, .716, .228, .269, .666, .929]: yp:=[.820, .202, .202, .521, .521, .820, .820, .227]:

> P2:=plot([seq([xp[i], yp[i]], i=1..nops(xp))]):

> Bs:=beta_2d(xp,yp,1,7): curve:=plot([Bs[1],Bs[2],t=-2+0.001..nops(xp)-1.001]): plots[display]([curve,P2]);

Change in a Beta-spline when one of its control points (with number i_0) moves.

> i0:=4: delta:=[rand(0..10)()/40, rand(0..10)()/40]:

> char:=i -> (1+signum(-t+i))*(1+signum(t-i+1))/4:

> pnew:=p[i0]+delta: for i from i0-2 to i0+1 do pp:=n[0](t-i+1)*p[i-1]+n[1](t-i+1)*p[i]+n[2](t-i+1)*p[i+1]+n[3](t-i+1)*p[i+2]: old[i]:=pp: new[i]:=subs(p[i0]=evalm(pnew),pp) od: r_d:=sum(char(j)*(new[j]-old[j]),j=i0-2..i0+1): r_new:=evalm(Bs+r_d):

> new_curve:=plot([r_new[1],r_new[2], t=-1.99..m-0.01],thickness=3):%;

> for i from -2 to m+2 do if i<> i0 then q[i]:=p[i] else q[i]:=pnew fi od:

> new_polygon:=plot([seq(q[i], i=0..m)]):%;

> poly2:=plot([[p[i0-1], pnew, p[i0+1]]]):

> plots[display]([new_polygon,P2,new_curve,curve]);

Play with beta_2d using the following data a) - b).

a) An example of random generating of an array of points in the plane.

> mm:=7: xp:=[seq(rand(1..10)(), j=1..mm)]: yp:=[seq(rand(1..10)(), j=1..mm)]: P:=plot([seq([xp[i], yp[i]], i=1..nops(xp))]):

b) Data for car profile

> xp:=[226,348,356,400,410,452,470,452,438,496,416,412,430,428,394,344,232,164,58,38,36,98,100,148,158,228,226]:

> yp:=[21,17,5,4,18,24,55,62,82,89,83,79,79,63,68,94,87,62,53,34,21,16,2,1,13,21,21]:

> Bs:=beta_2d(xp,yp,1,7): curve:=plot([Bs[1],Bs[2],t=-2+0.001..nops(xp)-1.001]): plots[display]([curve,P],scaling=constrained);

Analogous procedure for deriving and plotting in .

> beta_3d := proc(xp,yp,zp,beta1,beta2) local s,n,i,p,pp,m; global spl,d,b1,b2; b1:=beta1; b2:=beta2; d:=evalf(2*b1^3+4*b1^2+4*b1+b2+2);n[0]:=t->2*b1^3*(1-t)^3/d;n[1]:=t->(2*b1^3*t*(t^2-3*t+3)+ 2*b1^2*(t^3-3*t^2+2)+2*b1*(t^3-3*t+2)+b2*(2*t^3-3*t^2+1))/d; n[2]:=t->(2*b1^2*t^2*(-t+3)+2*b1*t*(-t^2+3)+b2*t^2*(-2*t+3)+2*(-t^3+1))/d; n[3]:=t->2*t^3/d;m:=nops(xp)-1; for s from 1 to m+1 do p[s-1]:=[xp[s], yp[s], zp[s]] od; p[-1]:=p[0]; p[m+1]:=p[m]; p[-2]:=p[0]; p[m+2]:=p[m]; pp:=n[0](t-i+1)*p[i-1]+n[1](t-i+1)*p[i]+n[2](t-i+1)*p[i+1]+n[3](t-i+1)*p[i+2]; spl:=evalm(sum((1+signum(-t+i))*(1+signum(t-i+1))/4*pp, i=-1..m));RETURN(plots[spacecurve](spl, t=-1.999..m-0.001)) end:

Use the procedure beta_3d(xp, yp, zp) to plot the space curve.

> xp:=[.056, .287, .655, .716, .228, .269, .666, .929]: yp:=[.820, .202, .202, .521, .521, .820, .820, .227]: zp:=[1/4,1/4,0,0,0,0,-1/4,-1/4]:

> polygon:=plots[pointplot3d]([seq([xp[j], yp[j], zp[j]],j=1..nops(xp))],symbol=circle): bs:=beta_3d(xp, yp, zp, 1, 1):

> plots[display]([bs,polygon],scaling=constrained,axes=boxed);

>

14.5 Interpolation Using Cubic Hermite's Curves

14.5.1 Elementary Cubic Hermite's Curve

Procedure for deriving and plotting in .

> herm1_2d:=proc(xp,yp,xq,yq) local s,n,i,m,p,q,pp; global spl; n[0]:=t->2*t^3-3*t^2+1; n[1]:=t->t^2*(-2*t+3); n[2]:=t->t*(t^2-2*t+1); n[3]:=t->t^2*(t-1); m:=nops(xp)-1; for s from 1 to m+1 do p[s-1]:=[xp[s], yp[s]]; q[s-1]:=[xq[s], yq[s]] od; pp:=n[0](t-i+1)*p[i-1]+n[1](t-i+1)*p[i]+n[2](t-i+1)*q[i-1]+n[3](t-i+1)*q[i]; RETURN(evalm(sum((1+signum(-t+i))*(1+signum(t-i+1))/4*pp,i=1..m))) end:

Use the procedure herm1_2d(xp,yp,xq,yq) for ploting the plane curve.

> xp:=[.056, .287, .655, .716, .228, .269, .666, .929]: yp:=[.820, .202, .202, .521, .521, .820, .820, .227]:

> xq:=[.25, .25, -.25, -.25, .25, .25, -.25, -.25]: yq:=[-.25, .25, -.25, .25, -.25, .25, -.25, .25]:

> P:=plot([seq([xp[j], yp[j]], j=1..nops(xp))]):

> vec:=i->plottools[arrow]([xp[i-1], yp[i-1]], [xq[i-1], yq[i-1]], .001,.02,.1): V:=seq(vec(i+1),i=1..nops(xp)):

> H1:=herm1_2d(xp,yp,xq,yq): curve:=plot([H1[1],H1[2],t=.01..nops(xp)-1.01]): plots[display]([curve,P,V],scaling=constrained);

>

14.5.2 Composed Cubic Hermite's Curve

Procedure for deriving and plotting in . The above system is solved in the procedure.

> herm2_2d := proc(xp, yp, xq, yq) local eq,a,b,ss,s,n,i,j,m,p,q,pp; n[0]:=t->2*t^3-3*t^2+1; n[1]:=t->t^2*(-2*t+3); n[2]:=t->t*(t^2-2*t+1); n[3]:=t->t^2*(t-1); m:=nops(xp)-1; p:=array(1..m+1); q:=array(1..m+1); a:=array(1..m-1, 1..m+1); b:=array(1..m-1, 1..m+1); for i from 1 to m-1 do for j from 1 to m+1 do if j=i then a[i,j]:=1; b[i,j]:=-3 elif j=i+1 then a[i,j]:=4; b[i,j]:=0 elif j=i+2 then a[i,j]:=1; b[i,j]:=-3 else a[i,j]:=0; b[i,j]:=0 fi od od; eq:=evalm(a&*q-b&*p); ss:=solve({seq(eq[i]=0, i=1..m-1)},{seq(q[i], i=2..m)}); assign(ss); q[1]:=[xq[1],yq[1]]; q[m+1]:=[xq[2],yq[2]]; for s from 1 to m+1 do p[s]:=[xp[s],yp[s]] od; i:='i'; pp:=n[0](t-i+1)*p[i]+n[1](t-i+1)*p[i+1]+n[2](t-i+1)*q[i]+n[3](t-i+1)*q[i+1]; RETURN(evalm(sum((1+signum(-t+i))*(1+signum(t-i+1))/4*pp,i=1..m))) end:

Plot the plane curve.

> xp:=[.056, .287, .655, .716, .228, .269, .666, .929]: yp:=[.820, .202, .202, .521, .521, .820, .820, .227]:xq:=[.1, -.1]: yq:=[.1, -.1]:

> vecs:=plots[display](plottools[arrow]([xp[1],yp[1]],[xq[1],yq[1]], 0.001, 0.02, 0.1), plottools[arrow]([xp[nops(xp)],yp[nops(yp)]],[xq[2],yq[2]],0.001,0.02,0.1)):

> polygon:=plot([seq([xp[j], yp[j]], j=1..nops(xp))]):

> H2:=herm2_2d(xp,yp,xq,yq): curve:=plot([H2[1],H2[2],t=0.01..nops(xp)-1.01]): plots[display]([vecs,curve,polygon]);

14.6 Composed Catmull-Rom Spline Curves

Procedure for deriving and plotting in .

> restart:

> crom_2d := proc(xp, yp) local s,n,i,p,pp,m; n[0]:=t-> -t*(1-t)^2/2; n[1]:=t-> (3*t^3-5*t^2+2)/2; n[2]:=t-> t*(-3*t^2+4*t+1)/2; n[3]:=t-> t^2*(t-1)/2; m:=nops(xp)-1; for s from 1 to m+1 do p[s-1]:=[xp[s], yp[s]] od; pp:=n[0](t-i+1)*p[i-1]+n[1](t-i+1)*p[i]+n[2](t-i+1)*p[i+1]+n[3](t-i+1)*p[i+2]; RETURN(evalm(sum((1+signum(-t+i))*(1+signum(t-i+1))/4*pp, i=1..m-2))) end:

Plot a plane curve.

> xp:=[.056, .287, .655, .716, .228, .269, .666, .929]: yp:=[.820, .202, .202, .521, .521, .820, .820, .227]:

> P3:=plot([seq([xp[j], yp[j]], j=1..nops(xp))],thickness=2):

> for i from 1 to nops(xp)-2 do v[i-1]:= plots[display](plottools[arrow]([xp[i], yp[i]], [xp[i+2]-xp[i], yp[i+2]-yp[i]], 0.001, 0.01, 0.1)) od:

> vecs:=seq(v[i-1], i=1..nops(xp)-2): cr:=crom_2d(xp,yp):

> curve1:=plot([cr[1], cr[2], t=0.01..nops(xp)-3.01],thickness=2):

> plots[display]([curve1, P3, vecs],scaling=constrained);

>