Tải bản đầy đủ (.pdf) (16 trang)

Đồ họa máy tính - Chương 6 ppt

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (908.44 KB, 16 trang )


30
Cho; }
Mhvanban;
END.

Chương VI. Hình học Fractal

I. Sự cần thiết của hình học Fractal


Hình học là ngôn ngữ đặc biệt để mô phỏng tự nhiên, và hình học Euclide đã ngự trị
một thời gian dài trong lĩnh vực mô tả, xử lý các hình dạng của tự nhiên. Tuy nhiên trong
thế giới thực có một lớp hình dạng không dễ dàng được mô tả bởi hình học Euclide như:
núi, mây, trời, biển Đặc tính của những đối tượng này là khi phóng to một phần chi tiết
nào đó thì sẽ có được dạng lặ
p lại của toàn hình, đặc tính đó được gọi là tự tương tự (self-
similarity). Hình học Fractal (viết tắt của Fractional – phân đoạn) ra đời để thích nghi với
việc mô phỏng lớp hình dạng đó: lớp hình có đặc tính “Fractal” – tự tương tự. (Xem và chạy
thử file fractal.exe)
Đường cong Fractal không thể được mô tả như đường hai chiều thông thường, mặt
Fractal không thể mô tả như mặt 3 chiều mà
đối tượng Fractal có thêm chiều hữu tỷ. Mặc dù
các đối tượng Fractal trong từng trường hợp cụ thể chỉ chứa một số hữu hạn chi tiết, nhưng
nó chứa đựng bản chất cho phép mô tả vô hạn chi tiết, tức là tại một thời điểm xác định thì
là hữu hạn, nhưng xét về tổng thể là vô hạn vì bản chất Fractal cho phép phóng đại lên một
mức độ b
ất kỳ một chi tiết tùy ý.
Hiện nay hình học Fractal và các khái niệm của nó đã trở thành công cụ trung tâm
trong các lĩnh vực của khoa học tự nhiên như: vật lý, hóa học, sinh học, địa chất học, khí
tượng học, khoa học vật liệu


Để hiểu thế nào là hình học Fractal, ta hãy so sánh với hình học Euclide cổ điển

Hình học Euclide Hình học Fractal
1) Xuất hiện từ rất lâu, trên 2000 năm trước 1) Xuất hiện năm 1975 (năm nhà toán học
Benoit Mandelbrot công bố công trình về
tập Mandelbrot)
2) Vật thể hình học Euclide có kích thước
đặc trưng
2) Không có kích thước xác định
3) Thích hợp với việc mô tả những thực thể
được tạo ra bởi con người.
3) Thích hợp để mô tả những vật thể trong
tự nhiên
4) Được mô tả bởi công thức (phương trình
tham số, phương trình bề mặt, quỹ đạo
)
4)
Được mô tả bởi thuật toán lặp

Hình học Euclide cho sự mô tả gọn gàng, chính xác những vật thể được tạo bởi con người
(khối lập phương, mặt trụ, mặt cầu ) nhưng không thích hợp khi dùng để mô tả những
hình dạng tự nhiên vì đòi hỏi một khối lượng tính toán (số và bậc của phương trình, ố lượng
biến ) rất cồng kềnh mà vẫn không chính xác. Còn sự mô tả của hình học Fractal (các
thuật lặp) lạ
i đặc biệt thích hợp với việc tạo sinh bằng máy tính. Thực thể Fractal là kết quả
của một quá trình lặp theo một thuật toán xác định, được tạo sinh lý tưởng bằng máy tính và
rất khó được tạo một cách thủ công.


31

II Một số khái niệm cơ bản


Các thực thể Fractal có 3 đặc tính quan trọng:

Tự tương tự (self-similarity)

Tự tương tự đa phần (statistical self-similarity)

Tự Affine
Chúng ta chỉ khảo sát đặc tính đầu tiên và quan trọng nhất: đặc tính tự tương tự (self-
similarity)
Một thực thể có đặc tính tự tương tự nếu nó là hợp của N tập con không giao nhau,
mỗi tập con được tạo sinh từ tập gốc qua các phép biến đổi như: co dãn, dịch chuyển, quay.
Phát biểu một cách hình thức hơn, xét tập S gồm những điểm:
x = (x
1
, x
2
, x
E
) trong không gian E chiều
Dưới phép đồng dạng với hệ số co 0 < T < 1, tập S biến thành tập TS với những điểm:
Tx = (Tx
1
, Tx
2
, Tx
E
)

Tập S là tự tương tự nếu S là hợp của N tập con không giao nhau, mỗi tập con tương đương
với TA (có thể sai khác một phép tịnh tiến, quay hoặc vị tự). Khi đó số chiều của S được
định nghĩa bởi
T
N
D
1
log
log
=

Tập S cũng được gọi là tự tương tự nếu các tập con được tạo sinh từ tập gốc theo các hệ số
co T
i
khác nhau. Trong trường hợp này số chiều D được tính từ công thức sau
1
1
=

=
N
i
D
i
T


III Ví dụ minh họa

Ta hãy xét một ví dụ minh họa tính tự tương tự của một thực thể Fractal kinh điển: đường

Von-Koch. Đường Von- Koch
(còn gọi là “Bông hoa tuyết Von-Koch” như trong
Wikipedia) là một trong những đường Fractal được công bố sớm nhất, vào năm 1904 bởi
nhà toán học Thụy Điển Helge Von Koch. Thuật toán lặp cho đường Von-Koch gồm những
bước sau:
a)
Một đoạn thẳng cho trước được chia làm 3 phần bằng nhau
b)
Đoạn giữa được thay bởi 2 đoạn có chiều dài tương đương
c)
Mỗi đoạn trong số 4 đoạn này lại được thay bởi 4 đoạn mới có chiều dài bằng 1/3
đoạn trước
d)
Quá trình cứ thế lặp lại


32


Đặc điểm của đường Von-Koch
• Đường cong này có tính tự tương tự, mỗi phần nhỏ khi được phóng to có thể tạo sinh
lại giống như phần lớn hơn, nói cách khác nó bất biến dưới sự phóng to hình.

Qua mỗi bước lặp, độ dài đường von-Koch tăng lên 4/3 lần

Đường cong (sau vô hạn bước) có độ dài vô hạn mặc dù nó chỉ chiếm một phần diện
tích hữu hạn của mặt phẳng

Không tự cắt


Thuật toán tạo sinh đường Von-Koch khá đơn giản, nhưng không có công thức đại số
để xác định những điểm trên đường cong

Số chiều của đường Von-Koch là hữu tỷ:
26,1
)3log(
)4log(
1
log
log
≈=






=
T
N
D


a)
b)
c)

33
D phản ánh mức độ lan tỏa của đường cong. Khi D biến thiên từ 1 đến 2, đường cong biến
thiên từ đường thẳng lan dần đến lấp đầy mặt phẳng hơn.


Số bước lặp Độ dài phân đoạn Số phân đoạn Tổng chiều dài đường Koch
1 1 1 1.00
2 1/3 4 1.33
3 1/9 16 1.77
4 1/27 64 2.37
5 1/81 256 3.16
6 1/243 1024 4.21

10 1/19683 262144 13.31
25 1/2.82e+11 2.81e+14 996.62
50 1/2.39e+23 3.17e+29 1324335.72
100 1/1.71e+47 4.02e+59 2338486807656.00

Chương trình vẽ đường Von-Koch
{ Vẽ 3 đường Von Koch giáp nhau tạo thành hình bông tuyết}
Uses crt,graph;
{ hệ số đổi từ độ sang radian }
Const
RADS = 0.017453293;
Var
i,gd,gm:integer;
temp:real;
Procedure Koch(dir:integer; len:real; n:integer);

34
Begin
if (n>0) then
begin
Koch(dir, len / 3, n-1);

dir := dir + 60;
Koch(dir, len / 3, n-1);
dir := dir - 120;
Koch(dir, len / 3, n-1);
dir := dir + 60;
Koch(dir, len / 3, n-1);
end
else
linerel(round(len * cos(RADS * dir)), round(len * sin(RADS * dir)));
End;

Begin
gd:=detect;
initgraph(gd,gm,'');

for i:=1 to 4 do
begin
setcolor(White);
rectangle(0, 0, getmaxx, getmaxy);
moveto(100,350); Koch(0, 420 , i);
setcolor(blue); Koch(-120, 420 , i);
setcolor(yellow); Koch(120, 420 , i);
readln;
cleardevice;
end;
closegraph;
End.

Đường Hilbert
do nhà toán họa Đức David Hilbert công bố năm 1891. Độ dài của nó tại

bước lặp thứ n là
n
n
n
L
2
1
2 −=

tức là độ dài tăng theo hàm mũ đối với n

35


Quay 90
0

thì như
nhau
Cả 4 quy tắc (rules) thực chất chỉ là 1

36

Chương trình vẽ đường Hilbert
{Vẽ các đường Hilbert}
Uses Crt,Graph;
Var
gd,gm,h:integer;
Procedure A (i:integer);FORWARD;
Procedure B (i:integer);FORWARD;

Procedure C (i:integer);FORWARD;
Procedure D (i:integer);FORWARD;

Procedure A(i:integer);
Begin
if (i>=0) then
Begin
D(i-1); linerel(-h, 0);
A(i-1); linerel(0, -h);
A(i-1); linerel(h, 0);
B(i-1);
End;
End;

Procedure B(i:integer);
Begin
if (i>=0) then
Begin
C(i-1); linerel(0, h);
B(i-1); linerel(h, 0);
B(i-1); linerel(0, -h);
A(i-1);
End;
End;

Procedure C(i:integer);
Begin

37
if (i>=0) then

Begin
B(i-1); linerel(h, 0);
C(i-1); linerel(0, h);
C(i-1); linerel(-h, 0);
D(i-1);
End;
End;

Procedure D(i:integer);
Begin
if (i>=0) then
Begin
A(i-1); linerel(0, -h);
D(i-1); linerel(-h, 0);
D(i-1); linerel(0, h);
C(i-1);
End;
End;

Procedure Hilbert;
Var
i:integer;
Begin
for i:=0 to 5 do
begin
h:= 30 - 5 * i;
moveto(getmaxx - 130, getmaxy - 50);
A(i);
readln; cleardevice;
end;

End;

Begin
gd:=detect;
initgraph(gd,gd,'');
setcolor(YELLOW);
rectangle(0, 0, getmaxx, getmaxy);
Hilbert;
closegraph;
End.


38

Chương trình vẽ Nhân sư (Sphinx)

{ Vẽ con nhân sư Sphinx }
Uses Crt,Graph;
{ hệ số đổi từ độ sang radian }
Const
RADS = 0.017453293;
Var
curangle,curx, cury:real;
gd,gm:integer;

Procedure lineforward(angle, length:real);
Begin
curangle :=curangle+ angle;
curx := curx + length*cos(curangle*RADS);
cury := cury + length*sin(curangle*RADS);

lineto(round(curx), round(cury));
End;

Procedure moveforward(angle,length:real);
Begin
curangle := curangle + angle;
curx := curx + length*cos(curangle*RADS);
cury := cury + length*sin(curangle*RADS);
lineto(round(curx), round(cury));
End;


39
Procedure Sphinx(angle, length: real; level,leftright:integer);
Var
len4, len2, len1, oldx, oldy, oldangle: real;
Begin
if (leftright<>0) then
Begin
if (level = 0) then
begin
len1 := length / 3;
lineforward(angle, length);
lineforward(-120,len1*2);
lineforward(-120,len1);
lineforward(+60,len1);
lineforward(-60,len1);
end
else
begin

Sphinx(angle, length, 0, leftright);
len4 := length / 4;
Sphinx(240, len4, 0, 1);
moveforward(240, len4);
Sphinx(0, len4, 0, 1);
moveforward(240, len4);
Sphinx(0, len4, 0, 1);
moveforward(240, len4);
Sphinx(0, len4, 0, 1);
moveforward(240, len4);
moveforward(-120, len4*2/3);
Sphinx(0, len4, 0, 0);
moveforward(240, len4);
Sphinx(0, len4, 0, 0);
moveforward(-180, len4*2/3);
Sphinx(-120, len4, 0, 0);
moveforward(240, len4/3);
Sphinx(-240, len4, 0, 1);
moveforward(240, len4);
Sphinx(0, len4, 0, 1);
moveforward(240, len4);
Sphinx(-60, len4, 0, 0);
moveforward(-180, len4*2/3);
lineforward(-60, len4);
moveforward(60, len4/3);
moveforward(-120, len4);
Sphinx(-180, len4, 0, 0);
end;
end
else

begin

40
if (level = 0) then
begin
len1 := length / 3;
lineforward(angle, length);
lineforward(-120,len1);
lineforward(-60,len1);
lineforward(60,len1);
lineforward(-120,len1*2);
end
else
begin
Sphinx(angle, length, 0, leftright);
len4 := length / 4;
end;
end;
End;

Begin
curangle := 0.0;
gd:=detect;
initgraph(gd,gm,'');
moveto(10, 470);
curx := 10;
cury := 470;
Sphinx(0, 600, 1, 1);
readln;
closegraph;

End.
Chương trình vẽ Phong cảnh (Fractal.exe)
Uses crt,graph;
Const
CLIP_ON = 1;
Var
n,c,t,mau:integer;
hs,go:real;
i,gd,gm:integer;
ch:char;

Function dau:integer;
Begin
if (random(2) = 0) then
dau:= -1
else
dau:= 1;
End;

Procedure cay(x,y:integer; h,g,gw:real; k:integer);

41
Var
x1,y1,i,j,d,leaf,c:integer;
dg,tt:real;
Begin
if (k > 0) then
for j:= 1 to (random(t) + t) do
begin
x1:= x + round(h * cos(g));

y1:= y + round(h * sin(g));
setcolor(DARKGRAY);
for i:= 0 to round((h/35)*(h/35)) do
begin
line(x + i, y, x1 + i, y1);
delay(10); {Ve cay cham de quan sat }
for d:= 1 to round((h/5)) do
begin
tt:= random(1);
putpixel(round((1-tt)*x+tt*x1+i),
round((1-tt)*y+tt*y1), LIGHTGRAY);
end;
end;
dg := gw/(2*n+1);
for i:= -n to n do
if (random(1000)*0.001 > 0.5) then
cay(x1,y1,h*(0.5+(random(1000)*0.001)/3),g+i*dg,gw*hs,k-1);
x := x1;
y := y1;
g := g + PI/18;
end
else
begin
setfillstyle(1,random(15));
setcolor(random(15));
for leaf:= 1 to 2 do
fillellipse(x+random(8)*dau,y+random(5)*dau,random(5)+2,random(2)+1);
for leaf:= 1 to 70 do
begin
case leaf of

0 20:
begin
putpixel(x+random(15)*dau,y+random(5)*dau,BLUE);
break;
end;
21 25:
begin
putpixel(x+random(15)*dau,y+random(5)*dau,LIGHTBLUE);
break;
end;

42
26 49:
begin
putpixel(x+random(15)*dau,y+random(5)*dau,LIGHTGREEN);
break;
end;
End;
End;
End;
End;

Procedure cloud(x,y:integer; Rx,Ry:real; k:integer);
Var
i:integer;
Begin
if (k > 0) then
for i:= 1 to 5 do
cloud(x+random(round(Rx)),y+random(round(Ry)),Rx*0.8,Ry*0.6,k-1)
else

for i:= 1 to round(sqrt(Rx*Ry)/3.5) do
putpixel(x+random(round(Rx)),y+random(round(Ry)),WHITE);
End;
Procedure phong;
Var
l,i:integer;
Begin
l := (getmaxy div 7) * 5;
mau:=random(15);
setfillstyle(1,mau);
bar(0,0,getmaxx,l);
setfillstyle(1,LIGHTGRAY);
bar(0,l,getmaxx,getmaxy);
for i:= 1 to 20000-1 do
case (random(8)) of
0 4:
begin
putpixel(random(getmaxx),l+random(getmaxy-l),GREEN);
break;
end;
5,6:
begin
putpixel(random(getmaxx),l+random(getmaxy-l),YELLOW);
break;
end;
7:
begin
putpixel(random(getmaxx),l+random(getmaxy-l),LIGHTRED);
break;
end;


43
end;
if (mau<>RED) then
Begin
if (mau<>BLACK) then
begin
setfillstyle(1,RED);
setcolor(RED);
end;
end
else
begin
setfillstyle(1,YELLOW);
setcolor(YELLOW);
end;
fillellipse(random(getmaxx div 2)+300,100,30,30);
for i:= 1 to 5 do
cloud(random(getmaxx),random(150)+10,random(60)+60,random(40)+20,5);
End;

BEGIN
randomize;
gd:=detect;
initgraph(gd,gm,'');
setviewport(0,0,getmaxx,getmaxy,CLIPON);
repeat
n := 1;
hs := 1.2;
go := PI /2.8;

t := 2;
phong;
cay(((getmaxx-100) div 5)+random(60),(getmaxy div 7)*6
+random(30)*dau,getmaxy div 6,-PI/2,go,5);
ch:=readkey;
until (ch=#27);
closegraph;
END.


44

Chương trình vẽ cây Pytago

{ Cây Pythagoras }
Uses Crt,Graph;
Const
{ 1 / sqrt(2) }
FCT = 0.7071067;
{ he so doi tu do sang radian }
RADS = 0.017453293;
Var
gd,gm:integer;

Procedure quadrat(x,y,a,angle:real);
Var
cp,sp:real;
Begin
setcolor(RED);
if (a < 35) then

setcolor(2);
if (a < 8) then
setcolor(7);
cp := a * cos(angle);
sp := a * sin(angle);
line(round(x), 200 - round(y), round(x + cp), 200 - round(y+sp));
line(round(x), 200 - round(y), round(x - cp), 200 - round(y+cp));
line(round(x+cp), 200 - round(y+sp), round(x - sp + cp), 200 - round(y+sp+cp));
line(round(x-sp), 200 - round(y+cp), round(x - sp + cp), 200 - round(y+sp+cp));
if (a > 2) then
Begin
quadrat(x - sp, y + cp, 3 * a / 5, angle + 0.93);
quadrat(x - sp + 3 * a / 5 * cos(angle + 0.93),
y + cp + 3 * a / 5 * sin (angle + 0.93), a * 4 / 5,
angle - 0.64);

45
End;
End;

Begin
gd:=detect;
initgraph(gd,gm,'');
setcolor(7);
quadrat(250, -120, 70, 0);
readln;
closegraph;
End.



×