You are on page 1of 15

ĐƯỜNG CONG B-SPLINE

Đường cong Bézier tỏ ra hiệu quả nhưng vẫn tồn tại khuyết điểm đó là các điểm điều khiển
có phạm vi toàn cục. Điều đó có nghĩa là nếu vị trí của một điểm điều khiển thay đổi thì hình
dạng của toàn bộ đường cong sẽ thay đổi. Hơn nữa, khi tăng điểm điều khiển thì số bậc của
đa thức cũng tăng theo, dẫn đến việc xấp xỉ đa giác điều khiển không tốt. Tất cả các vấn đề
trên có thể khắc phục bằng hình học B-Spline.

Chữ "B" trong B-Spline đại diện cho từ "basic" nghĩa là hàm cơ sở. Hàm cơ sở B-Spine bằng
không bên ngoài một đoạn nào đó, chính các đoạn này sẽ giới hạn phạm vi mà một điểm điều
khiển có ảnh hưởng đến đường cong.

Vì vậy, một B-Spline được định nghĩa bằng các điểm điều khiển và phạm vi các điểm điều
khiển này hoạt động. Phạm vi này được định nghĩa gián tiếp thông qua một đối tượng được
gọi là vector knot. Vector knot được chia thành từng đoạn và các hàm cơ sở B-Spline được
định nghĩa từng phần cho các đoạn này với một độ liên tục nhất định giữa các đoạn. Vì số
lượng các đoạn là bất kỳ, bậc của đa thức có thể được chọn độc lập với số lượng các điểm
điều khiển. Do đó, một đường cong có thể xấp xỉ một số lượng lớn các điểm điều khiển ngay
cả ở bậc đa thức thấp.

Vector Knot

Một vector knot  là một dãy không giảm các số thực (gọi là knot), đại diện cho các tọa độ
trong không gian tham số của đường cong

  1 ,  2 ,,  n  p 1 ,  i   i 1 , i  1, n  p  1

trong đó p là bậc của B-Spline và n là số lượng các hàm cơ sở (hay điểm điều khiển) cần
thiết để biểu diễn B-Spline. Nếu các điểm knot được chia cách đều nhau, vector knot được
gọi là đều. Các hàm cơ sở B-Spline sẽ liên tục C  bên trong một khoảng knot i ;i 1  và liên

tục C p 1 tại một giá trị knot riêng biệt. Một giá trị knot có thể xuất hiện nhiều hơn 1, và số lần
xuất hiện một giá trị knot trong vector knot được gọi là bội của knot đó. Tại một knot có bội k
, độ liên tục là C p  k , nghĩa là độ liên tục của B-Spline sẽ giảm đi khi tăng bội của knot.

Trong trường hợp tổng quát, đường cong B-Spline sẽ không đi qua hai điểm điều khiển đầu
và cuối. Đường cong chỉ đi qua hai điểm này nếu điểm knot đầu và cuối có bội là p  1 , và một
vector knot như vậy được gọi là vector knot mở
 
  a ,, a ,  p  2 ,,  n , b
, a ,,b 
, b
 p 1 p 1 

Các hàm cơ sở

Dựa trên vector knot và bậc của đa thức, các hàm cơ sở B-Spline được tính bằng công thức
đệ qui Cox-de Boor

x  i 1 i  p  
Ni , p    Ni , p 1    Ni 1, p 1   (1)
i  p  i 1 i  p  i 1

1,   i ;i 1 


trong đó N i ,0     .
0,   i ; i 1 

Phương trình (1) có thể chứa thương số có mẫu bằng không. Trong trường hợp đó, thương
số được định nghĩa bằng không.

Ví dụ 1: Cho vector knot   0,0,0,1, 2,2,3,4,5,5,5 . Viết chương trình Matlab xác định các

hàm cơ sở B-Spline bậc 0,1,2.

Chương trình con 1: Hàm cơ sở B-Spline bậc 0


function N=funcN0(xi,KNOT)
n=length(xi);
N=zeros(1,n);
if (KNOT(1)==KNOT(2))
for i=1:n
N(i)=0;
end
else
for i=1:n
if (xi(i)>=KNOT(1))&&(xi(i)<KNOT(2))
N(i)=1;
end
end
end
N';
Sử dụng chương trình con 1 vào một script M-File có tên N0
clear all;
close all;
clc;
xi=0:0.01:5;
knotvector=[0 0 0 1 2 2 3 4 5 5 5];
m=length(knotvector);
n=length(xi);
figure;
axis([0 5 0 2]);
for j=1:(m-1)
subplot(5,2,j)
KNOT=[knotvector(j) knotvector(j+1)];
plot(xi,funcN0(xi,KNOT));
end
Chạy N0 ta được kết quả
Chương trình con 2: Hàm cơ sở B-Spline bậc 1
function N_1=funcN1(xi,KNOT1)
KNOT11=[KNOT1(1) KNOT1(2)];
KNOT12=[KNOT1(2) KNOT1(3)];
N01=funcN0(xi,KNOT11);
N02=funcN0(xi,KNOT12);
n=length(xi);
N_1=zeros(1,n);
if (KNOT1(1)==KNOT1(2))&&(KNOT1(2)==KNOT1(3))
for i=1:n
N_1(i)=0;
end
elseif (KNOT1(1)==KNOT1(2))&&(KNOT1(2)~=KNOT1(3))
for i=1:n
N_1(i)=(KNOT12(2)-xi(i))/(KNOT12(2)-KNOT12(1))*N02(i);
end
elseif (KNOT1(1)~=KNOT1(2))&&(KNOT1(2)==KNOT1(3))
for i=1:n
N_1(i)=(xi(i)-KNOT11(1))/(KNOT11(2)-KNOT11(1))*N01(i);
end
else
for i=1:n
N_1(i)=(xi(i)-KNOT11(1))/(KNOT11(2)-
KNOT11(1))*N01(i)+(KNOT12(2)-xi(i))/(KNOT12(2)-KNOT12(1))*N02(i);
end
end
N_1';

Sử dụng chương trình con 2 vào một script M-File có tên N1


clear all;
close all;
KNOT1=[2 3 4];
xi=0:0.001:5;
knotvector=[0 0 0 1 2 2 3 4 5 5 5];
m=length(knotvector);
n=length(xi);
figure;
axis([0 5 0 2]);
for j=1:(m-2)
subplot(3,3,j)
KNOT1=[knotvector(j) knotvector(j+1) knotvector(j+2)];
plot(xi,funcN1(xi,KNOT1));
end
Chạy N1 ta được kết quả
Chương trình con 3: Hàm cơ sở B-Spline bậc 2

function N_2=funcN2(xi,KNOT2)
KNOT21=[KNOT2(1) KNOT2(2) KNOT2(3)];
KNOT22=[KNOT2(2) KNOT2(3) KNOT2(4)];
N21=funcN1(xi,KNOT21);
N22=funcN1(xi,KNOT22);
n=length(xi);
N_2=zeros(1,n);
if (KNOT2(1)==KNOT2(3))&&(KNOT2(2)==KNOT2(4))
for i=1:n
N_2(i)=0;
end
elseif (KNOT2(1)==KNOT2(3))&&(KNOT2(2)~=KNOT2(4))
for i=1:n
N_2(i)=(KNOT22(3)-xi(i))/(KNOT22(3)-KNOT22(1))*N22(i)
end
elseif (KNOT2(1)~=KNOT2(3))&&(KNOT2(2)==KNOT2(4))
for i=1:n
N_2(i)=(xi(i)-KNOT21(1))/(KNOT21(3)-KNOT21(1))*N21(i)
end
else
for i=1:n
N_2(i)=(xi(i)-KNOT21(1))/(KNOT21(3)-
KNOT21(1))*N21(i)+(KNOT22(3)-xi(i))/(KNOT22(3)-KNOT22(1))*N22(i)
end
end
N_2';
Sử dụng chương trình con 3 vào một script M-File có tên N2

clear all;
close all;
xi=0:0.01:5;
knotvector=[0 0 0 1 2 2 3 4 5 5 5];
m=length(knotvector);
n=length(xi);
figure;
axis([0 5 0 2]);
for j=1:(m-3)
subplot(2,4,j)
KNOT2=[knotvector(j) knotvector(j+1) knotvector(j+2)
knotvector(j+3)];
plot(xi,funcN2(xi,KNOT2));
end
Chạy N2 ta được

Ta có thể biểu diễn các hàm cơ sở B-Spline bậc 2 trên cùng một đồ thị như sau:
Ví dụ 2: Cho vector knot   0,0,0,0,1, 2,3, 4,4,4,4 . Viết chương trình Matlab xác định các

hàm cơ sở B-Spline bậc 3.

Chương trình con 4: Hàm cơ sở B-Spline bậc 3


function N_3=funcN3(xi,KNOT3)
KNOT31=[KNOT3(1) KNOT3(2) KNOT3(3) KNOT3(4)];
KNOT32=[KNOT3(2) KNOT3(3) KNOT3(4) KNOT3(5)];
N31=funcN2(xi,KNOT31);
N32=funcN2(xi,KNOT32);
n=length(xi);
N_3=zeros(1,n);
if (KNOT3(1)==KNOT3(4))&&(KNOT3(2)==KNOT3(5))
for i=1:n
N_3(i)=0;
end
elseif (KNOT3(1)==KNOT3(4))&&(KNOT3(2)~=KNOT3(5))
for i=1:n
N_3(i)=(KNOT32(4)-xi(i))/(KNOT32(4)-KNOT32(1))*N32(i)
end
elseif (KNOT3(1)~=KNOT3(3))&&(KNOT3(2)==KNOT3(4))
for i=1:n
N_3(i)=(xi(i)-KNOT31(1))/(KNOT31(4)-KNOT31(1))*N31(i)
end
else
for i=1:n
N_3(i)=(xi(i)-KNOT31(1))/(KNOT31(4)-
KNOT31(1))*N31(i)+(KNOT32(4)-xi(i))/(KNOT32(4)-KNOT32(1))*N32(i)
end
end
N_3';
Sử dụng chương trình con 4 vào một script M-File có tên N3
clear all;
close all;
xi=0:0.01:4;
knotvector=[0 0 0 0 1 2 3 4 4 4 4];
m=length(knotvector);
n=length(xi);
figure;
axis([0 5 0 5]);
axis equal
for j=1:(m-4)
KNOT3=[knotvector(j) knotvector(j+1) knotvector(j+2)
knotvector(j+3) knotvector(j+4)];
plot(xi,funcN3(xi,KNOT3));
hold on
end
Chạy N3 ta được

Với các kết quả đã đạt được, bằng phương pháp tương tự, ta viết chương trình con cho các
hàm cơ sở B-Spline bậc p .

Chương trình con 5: Hàm cơ sở B-Spline bậc p


function N_p=funcNp(xi,p,KNOTp)
n=length(xi);
N_p=zeros(1,n);
if (p==0)
N_p=funcN0(xi,KNOTp);
else
for j=1:p
KNOTp1=KNOTp(1:(j+1));
KNOTp2=KNOTp(2:(j+2));
Np1=funcNp(xi,j-1,KNOTp1);
Np2=funcNp(xi,j-1,KNOTp2);
if (KNOTp(1)==KNOTp(1+j))&&(KNOTp(2)==KNOTp(j+2))
for i=1:n
N_p(i)=0;
end
elseif (KNOTp(1)==KNOTp(1+j))&&(KNOTp(2)~=KNOTp(j+2))
for i=1:n
N_p(i)=(KNOTp2(1+j)-xi(i))/(KNOTp2(1+j)-
KNOTp2(1))*Np2(i)
end
elseif (KNOTp(1)~=KNOTp(1+j))&&(KNOTp(2)==KNOTp(2+j))
for i=1:n
N_p(i)=(xi(i)-KNOTp1(1))/(KNOTp1(j+1)-KNOTp1(1))*Np1(i)
end
else
for i=1:n
N_p(i)=(xi(i)-KNOTp1(1))/(KNOTp1(j+1)-
KNOTp1(1))*Np1(i)+(KNOTp2(j+1)-xi(i))/(KNOTp2(j+1)-KNOTp2(1))*Np2(i)
end
end
end
end
N_p';

Các đường B-Spline

Một đường cong B-Spline bậc p được xác định bằng tổ hợp tuyến tính của các điểm điều
khiển và các hàm cơ sở tương ứng

n
C     N i. p   Pi (2)
i 1

Ví dụ 3: Cho vector knot   0,0,0,0,1, 2,3, 4,4,4,4 . Viết chương trình Matlab xác định đường

cong B-Spline bậc 3 với các điểm điều khiển

P1  0;0  , P2  0,1 , P3 1;1 , P4  2.5, 0.5 , P5  4;2  , P6  5;2.5 , P7  6;1

Sử dụng chương trình con 5 và công thức (2) ta có chương trình sau (viết trên một Script M-
File có tên là Spline_Global)

clear all;
close all;
clc
knotvector=[0 0 0 0 1 2 3 4 4 4 4];
m=length(knotvector);
p=3;
ctrpoint=[0 0;0 1;1 1;2.5 -0.5;4 2;5 2.5;6 1];
xi=0:0.01:4;
n=length(xi);
BSP=zeros(n,m-p-1);
for j=1:(m-p-1)
KNOT3=[knotvector(j) knotvector(j+1) knotvector(j+2)
knotvector(j+3) knotvector(j+4)];
BSP(:,j)=funcNp(xi,p,KNOT3);
end
CurveBS3=zeros(n-1,2);
for i=1:(n-1)
for j=1:(m-p-1)
CurveBS3(i,1)=CurveBS3(i,1)+BSP(i,j)*ctrpoint(j,1);
CurveBS3(i,2)=CurveBS3(i,2)+BSP(i,j)*ctrpoint(j,2);
end
end
figure;
axis([-0.5 6.3 -1 3])
plot(ctrpoint(:,1),ctrpoint(:,2),'--o','Color','r');
hold on
plot(CurveBS3(:,1),CurveBS3(:,2));
Chạy Spline_Global ta được kết quả

Đạo hàm của hàm cơ sở B-Spline

Đạo hàm bậc nhất của hàm cơ sở B-Spline được tính theo công thức

dN i , p   p p
 N i , p 1     N i 1, p 1   (3)
d  i  p  i i  p 1  i 1

Những đạo hàm cấp cao hơn được tính bằng cách lấy đạo hàm từng vế của (3)

d k Ni, p   p d k 1 N i , p 1   p d k 1 N i 1, p 1  
  (4)
d k i  p   i d k 1 i  p 1  i 1 d k 1

d k Ni, p  
Để xác định ta có thể sử dụng công thức
d k
d k Ni , p   p! k
 k , j Ni  j , p  k  
 p  k ! 
 (5)
d k j 0

với

 0,0  1
 k 1,0
 k ,0 
 i  p  k 1   i
 k 1, j   k 1, j 1
k, j  , j  1, k  1
 i  p  j  k 1   i  j
 k 1, k 1
 k ,k 
 i  p 1   i  k

Ví dụ 4: Cho vector knot   0,0,0,1, 2,2,3,4,5,5,5 . Viết chương trình Matlab xác định đạo

hàm các hàm cơ sở B-Spline bậc 2.

Dùng chương trình con 5 ta viết chương trình tính đạo hàm của hàm cơ sở B-Spline bậc p .

Chương trình con 6: Đạo hàm hàm cơ sở B-Spline bậc p


function dN_p=funcDNp(xi,p,KNOTp)
n=length(xi);
dN_p=zeros(n,1);
KNOTp1=KNOTp(1:p+1);
KNOTp2=KNOTp(2:p+2);
Np1=funcNp(xi,p-1,KNOTp1);
Np2=funcNp(xi,p-1,KNOTp2);
if (KNOTp1(1+p)==KNOTp(1))&&(KNOTp2(1+p)==KNOTp2(1))
for i=1:n
dN_p(i)=0
end
elseif (KNOTp1(1+p)==KNOTp(1))&&(KNOTp2(1+p)~=KNOTp2(1))
for i=1:n
dN_p(i)=-p/(KNOTp2(1+p)-KNOTp2(1))*Np2(i)
end
elseif (KNOTp1(1+p)~=KNOTp(1))&&(KNOTp2(1+p)==KNOTp2(1))
for i=1:n
dN_p(i)=p/(KNOTp1(1+p)-KNOTp(1))*Np1(i)
end
else
for i=1:n
dN_p(i)=p/(KNOTp1(1+p)-KNOTp(1))*Np1(i)-p/(KNOTp2(1+p)-
KNOTp2(1))*Np2(i)
end
end
dN_p';
Sử dụng chương trình con 6, ta viết chương trình cho ví dụ 4 (trên một script M-File có tên là
derivative_of_N2)

clear all
close all
xi=0:0.005:5;
p=2;
KNOT=[0 0 0 1 2 2 3 4 5 5 5];
m=length(KNOT);
figure;
axis([0 5.2 -2 3]);
for j=1:(m-p-1)
KNOTp=[KNOT(j) KNOT(j+1) KNOT(j+2) KNOT(j+3)]
plot(xi,funcDNp(xi,p,KNOTp))
hold on
end
Chạy derivative_of_N2 ta được

Ví dụ 5: Cho vector knot   0,0,0,0,1, 2,3, 4,4,4,4 . Viết chương trình Matlab xác định đạo

hàm các hàm cơ sở B-Spline bậc 3.

Sử dụng chương trình con 6, ta viết chương trình cho ví dụ 5 (trên một script M-File có tên là
derivative_of_N3)
clear all
close all
xi=0:0.01:4;
p=3;
KNOT=[0 0 0 0 1 2 3 4 4 4 4];
m=length(KNOT);
figure;
axis([0 4.2 -10 10]);
for j=1:(m-p-1)
KNOTp=[KNOT(j) KNOT(j+1) KNOT(j+2) KNOT(j+3) KNOT(j+4)]
plot(xi,funcDNp(xi,p,KNOTp))
hold on
end
Chạy derivative_of_N3 ta được

Sử dụng chương trình con (5) và (6) ta xây dựng chương trình tính đạo hàm cấp k  k  p  cho

hàm cơ sở B-Spline bậc p .


Chương trình con 7: Đạo hàm cấp k  k  p  hàm cơ sở B-Spline bậc p
function dkN_p=funcDkNp(xi,p,k,KNOTp)
n=length(xi);
dkN_p=zeros(n,1);
if (k>p)
for i=1:n
dkN_p(i)=0;
end
elseif (k==0)
dkN_p=funcNp(xi,p,KNOTp);
elseif (k==1)
dkN_p=funcDNp(xi,p,KNOTp);
else
KNOTp1=KNOTp(1:(p+1));
KNOTp2=KNOTp(2:(p+2));
for j=2:k
Np1=funcDkNp(xi,p-1,j-1,KNOTp1);
Np2=funcDkNp(xi,p-1,j-1,KNOTp2);
if (KNOTp1(1)==KNOTp1(p+1))&&(KNOTp2(1)==KNOTp2(p+1))
for i=1:n
dkN_p(i)=0;
end
elseif (KNOTp1(1)~=KNOTp1(p+1))&&(KNOTp2(1)==KNOTp2(p+1))
for i=1:n
dkN_p(i)=p/(KNOTp1(p+1)-KNOTp1(1))*Np1(i);
end
elseif (KNOTp1(1)==KNOTp1(p+1))&&(KNOTp2(1)~=KNOTp2(p+1))
for i=1:n
dkN_p(i)=-p/(KNOTp2(p+1)-KNOTp2(1))*Np2(i);
end
else
for i=1:n
dkN_p(i)=p/(KNOTp1(p+1)-KNOTp1(1))*Np1(i)-
p/(KNOTp2(p+1)-KNOTp2(1))*Np2(i);
end
end
end
end

Ví dụ 6: Cho vector knot   0,0,0,0,1, 2,3, 4,4,4,4 . Viết chương trình Matlab xác định đạo

hàm cấp 1,2 và 3 các hàm cơ sở B-Spline bậc 3.

Sử dụng chương trình con 7, ta viết chương trình cho ví dụ 6 (trên một script M-File có tên là
derivative_k_of_N3)

clear all
close all
xi=0:0.01:4;
p=3;
KNOT=[0 0 0 0 1 2 3 4 4 4 4];
m=length(KNOT);
figure;
axis([0 4.2 -10 10]);
for k=1:3
subplot(1,3,k);
for j=1:(m-p-1)
KNOTp=KNOT(j:(j+p+1))
plot(xi,funcDkNp(xi,p,k,KNOTp));
hold on
end
end
Chạy derivative_k_of_N3 ta được

You might also like