Академический Документы
Профессиональный Документы
Культура Документы
Геометрические фракталы.
Алгебраические фракталы.
1
сосудистой системы), то алгебраические фракталы, или аттракторы, связаны
с процессами, протекающими во времени и кажущиеся на первый взгляд
хаотическими.
2
Рекурсивные алгоритмы.
условие остановки;
2) глубокая рекурсия. Если алгоритм вызывает слишком глубокую рекурсию,
3
Рекурсивное построение кривых Серпинского.
4
Отрезки, составляющие кривую, изображены со стрелками, которые
указывают направление их рисования. Сегменты, используемые для
соединения частей, представлены пунктирными линиями.
5
На рисунке 1.5 показано, как из четырех кривых 1-го порядка формируется
полная кривая Серпинского 2-го порядка. Каждая из подкривых обведена
пунктирными линиями.
6
С помощью стрелок типа → и ←, отображающих типы линий, которые
соединяют части кривых между собой (тонкие линии на рисунке 1.4), можно
перечислить рекурсивные зависимости между четырьмя типами кривых, как
показано на схеме ниже.
A: A B← D A
B: B C A B
C: C D→B C
D: D A C D
type
TCerpin = class(TForm) //имя формы – “Cerpin”
procedure SierpA(depth, dist:Integer; canvas: TCanvas);
procedure SierpB(depth, dist:Integer;canvas: TCanvas);
procedure SierpC(depth, dist:Integer;canvas: TCanvas);
procedure SierpD(depth, dist:Integer;canvas: TCanvas);
procedure FormPaint(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
Var
Cerpin: TCerpin;
7
Cerpin.Canvas.LineTo(Cerpin.Canvas.PenPos.X-dist,Cerpin.Canvas.PenPos.Y+0);
Cerpin.Canvas.LineTo(Cerpin.Canvas.PenPos.X-dist,Cerpin.Canvas.PenPos.Y-dist);
end else begin // если порядок кривой больше 1, то составляем кривую из меньших
кривых, как показано на рисунке 1.5
Cerpin.Canvas.Pen.Color:=clYellow;
SierpA(depth-1,dist,canvas);
Cerpin.Canvas.LineTo(Cerpin.Canvas.PenPos.X-dist,Cerpin.Canvas.PenPos.Y+dist);
SierpB(depth-1,dist,canvas);
Cerpin.Canvas.LineTo(Cerpin.Canvas.PenPos.X-dist,Cerpin.Canvas.PenPos.Y+0);
SierpD(depth-1,dist,canvas);
Cerpin.Canvas.LineTo(Cerpin.Canvas.PenPos.X-dist,Cerpin.Canvas.PenPos.Y-dist);
SierpA(depth-1,dist,canvas);
end;
end;
8
procedure TCerpin.SierpD(depth, dist: Integer;Canvas:TCanvas);
begin
if (depth=1) then begin
Cerpin.Canvas.Pen.Color:=clTeal;
Cerpin.Canvas.LineTo(Cerpin.Canvas.PenPos.X-dist,Cerpin.Canvas.PenPos.Y-dist);
Cerpin.Canvas.LineTo(Cerpin.Canvas.PenPos.X+0,Cerpin.Canvas.PenPos.Y-dist);
Cerpin.Canvas.LineTo(Cerpin.Canvas.PenPos.X+dist,Cerpin.Canvas.PenPos.Y-dist);
end else begin
Cerpin.Canvas.Pen.Color:=clTeal;
SierpD(depth-1,dist,canvas);
Cerpin.Canvas.LineTo(Cerpin.Canvas.PenPos.X-dist,Cerpin.Canvas.PenPos.Y-dist);
SierpA(depth-1,dist,canvas);
Cerpin.Canvas.LineTo(Cerpin.Canvas.PenPos.X+0,Cerpin.Canvas.PenPos.Y-dist);
SierpC(depth-1,dist,canvas);
Cerpin.Canvas.LineTo(Cerpin.Canvas.PenPos.X+dist,Cerpin.Canvas.PenPos.Y-dist);
SierpD(depth-1,dist,canvas);
end;
end;
procedure TCerpin.FormPaint(Sender: TObject); // выводим изображение кривых
Серпинского на канву формы с помощью события OnPaint.
begin
Cerpin.Canvas.MoveTo(dist,dist);
SierpB(depth,dist,Cerpin.Canvas);
Cerpin.Canvas.LineTo(Cerpin.Canvas.PenPos.X+dist,Cerpin.Canvas.PenPos.Y+dist);
//соединяем кривые разных типов (смотри рисунок 1.4)
SierpC(depth,dist,Cerpin.Canvas);
Cerpin.Canvas.LineTo(Cerpin.Canvas.PenPos.X+dist,Cerpin.Canvas.PenPos.Y-dist);
SierpD(depth,dist,Cerpin.Canvas);
Cerpin.Canvas.LineTo(Cerpin.Canvas.PenPos.X-dist,Cerpin.Canvas.PenPos.Y-dist);
SierpA(depth,dist,Cerpin.Canvas);
Cerpin.Canvas.LineTo(Cerpin.Canvas.PenPos.X-dist,Cerpin.Canvas.PenPos.Y+dist);
end;
Примечания.
9
окна. Событие не прописывают вручную. Поступают следующим образом, в
инспекторе объектов находят это событие и в поле, которое находится рядом
с ним, щелкают два раза мышкой. После этого активизируется окно кода
программы, где уже будет прописана заготовка для процедуры обработчика
события OnPaint.
10
Рекурсивное построение кривых Гильберта.
type
TForm1 = class(TForm)
procedure a(i:integer; canvas: Tcanvas);
procedure b(i:integer; canvas: Tcanvas);
procedure c(i:integer; canvas: Tcanvas);
procedure d(i:integer; canvas: Tcanvas);
procedure FormPaint(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
p: integer=11;
u: integer=13;
implementation
{$R *.dfm}
procedure Tform1.a(i: integer; canvas: Tcanvas);
begin
if i>0 then begin
d(i-1, canvas);
canvas.LineTo(canvas.PenPos.X+u, canvas.PenPos.Y);
a(i-1, canvas);
11
canvas.LineTo(canvas.PenPos.X, canvas.PenPos.Y+u);
a(i-1, canvas);
canvas.LineTo(canvas.PenPos.X-u, canvas.PenPos.Y);
c(i-1,canvas);
end;
end;
12
Рекурсивное построение кривой «Снежинка»
13
l l
l + + 2 = 200
4 4
каждого очередного звена в четыре раза меньше предыдущего. Если через l
обозначить длину первого звена, то справедливо следующее равенство:
1
1−
l× 4 n = 200
1 (сумма членов геометрической прогрессии)
1−
4
то есть
4 n −1
l = 200 × 3 × n
4 −1
Пусть снежинка состоит из одного звена и р ветвей, тогда соответствующая
программа проста. Основная ее часть ее имеет вид:
for i:=1 to p do
begin
x1:=trunc(x+L[k]*cos(2*pi*(i-1)/p));
y1:=trunc(y+L[k]*sin(2*pi*(i-1)/p));
{координаты конца очередного звена}
Flake.Canvas.MoveTo(x,y); {рисование звена}
Flake.Canvas.LineTo(x1,y1);
End;
14
Начинаем рисовать из центра, точки А, нарисовали отрезок АВ(a), если это
не последнее звено, то будем рисовать отрезок следующего звена ВС, звено
не последнее, поэтому продолжим. Предположим, что нарисовали СЕ, это
первая часть самой маленькой снежинки, наша программа должна работать
как набросок, то есть рисовать все ветви этой снежинки. После этого мы
должны вернуться в точку В. Так как это не последняя ветвь этой снежинки,
то мы снова должны нарисовать следующую ветвь – отрезок ВД(б), а затем
снова полностью самую маленькую снежинку. Что необходимо для
реализации этой логики? Пусть значение переменной k будет равно
текущему номеру звена снежинки, в начальный момент оно равно n. Тогда
при переходе из точек С, Д к точке В мы должны «вспомнить» координаты
точки В и номер ветви снежинки, рисуемой из точки В. При переходе от
точки В к А мы должны «вспомнить» координаты точки А и номер ветви
снежинки, рисуемой из точки А. Эта логика реализуется с помощью
рекурсии.
type
TFlake = class(TForm) //имя формы- “Flake”
procedure Snow(x,y,k: Integer);
procedure FormPaint(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
const
p=8;
var
Flake: TFlake;
x,y,i: integer;
n: integer;
L: array[1..8] of integer;
implementation
{$R *.dfm}
procedure TFlake.Snow(x,y,k: Integer);
var x1, i,y1: integer;
begin
if k>0 then
15
begin
for i:=1 to p do
begin
x1:=trunc(x+L[k]*cos(2*pi*(i-1)/p));
y1:=trunc(y+L[k]*sin(2*pi*(i-1)/p));
Flake.Canvas.MoveTo(x,y);
Flake.Canvas.LineTo(x1,y1);
snow(x1,y1,k-1); end; end;
end;
procedure TFlake.FormPaint(Sender: TObject);
begin
Flake.Canvas.Pen.Color:=clWhite;
L[n]:=trunc(200*3*exp((n-1)*ln(4))/(exp(n*ln(4))-1));
for i:=2 to n do
L[n-i+1]:=trunc(L[n]/exp((i-1)*ln(4)));
x:=300; y:=200;
Snow(x,y,n);
end;
end.
type
TTringle = class(TForm)
Panel1: TPanel;
16
Label3: TLabel;
Label2: TLabel;
Label1: TLabel;
Button1: TButton;
Button2: TButton;
procedure Triangle(xa, ya, xb, yb, xc, yc, n: Integer);
procedure FormPaint(Sender: TObject);
procedure FormShow(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Tringle: TTringle;
n,xa, ya, xb, yb, xc, yc,q : Integer;
w:string;
a: array[0..10]of TColor; //задаем массив цветов.
implementation
{$R *.dfm}
17
Tringle.Canvas.LineTo(xr,yr);
Triangle(xa, ya, xr, yr, xq, yq, n-1);
Triangle(xb, yb, xp, yp, xr, yr, n-1);
Triangle(xc, yc, xq, yq, xp, yp, n-1);
end;
end;
procedure TTringle.FormPaint(Sender: TObject);
begin
Tringle.Canvas.Pen.Color:=clPurple;
xc:=300; yc:=0; xb:=600; yb:=400; xa:=0; ya:=400;// задание начальных значений
Tringle.Canvas.MoveTo(xa,ya);
Tringle.Canvas.LineTo(xb,yb);
Tringle.Canvas.MoveTo(xb,yb);
Tringle.Canvas.LineTo(xc,yc);
Tringle.Canvas.MoveTo(xa,ya);
Tringle.Canvas.LineTo(xc,yc);
Triangle(xa,ya,xb,yb,xc,yc,StrToInt(w));
end;
18
Затем определяем значение каждого элемента массива, то есть каждому из
элемента массива присваиваем определенный цвет. Для того, чтобы при
каждом последующем повторении программа использовала другой цвет
организуем цикл с параметром for. Этот цикл имеет следующую структуру:
Do <оператор>;
19
Line (xp, yp)-(xr, yr), RGB(190, 190, 300)
Call triangle(xc, yc, xq, yq, xp, yp, n - 1)
Call triangle(xa, ya, xr, yr, xq, yq, n - 1)
Call triangle(xb, yb, xp, yp, xr, yr, n - 1)
End If End Sub
Private Sub Command1_Click()
treug.Scale (-50, -50)-(800, 600) // Задаем маштаб
treug.Cls //предварительно очищаем форму от предыдущего рисунка
n = Val(Text1.Text)
Line (xa, ya)-(xb, yb), RGB(90, 190, 300)
Line (xb, yb)-(xc, yc), RGB(90, 190, 300)
Line (xa, ya)-(xc, yc), RGB(90, 190, 300)
Call triangle(xa, ya, xb, yb, xc, yc, n)
End Sub
Private Sub Form_Load()
n = Val(Text1.Text)
xc = 300
yc = 0
xb = 600
yb = 400
xa = 0 ya = 400
End Sub
20
Имя Объекта может отсутствовать. В этом случае по умолчанию метод
применяется к экранной форме.
Параметр (XI, Y1) — (Х2, Y2) — это координаты границ отрезка или двух
углов прямоугольника — левого верхнего и правого нижнего (или наоборот
— правого нижнего и левого верхнего).
RGB(Red (код красного цв.), Green (код зеленого цв.), Blue (код синего цв.)
Параметр Флаг — это либо символ В, либо символы BF. В первом случае
рисуется не отрезок, а прямоугольник, во втором — закрашенный
прямоугольник. (Цвет закраски — это значение параметра Цвет.)
21
Построение данной кривой аналогично построению треугольника
Серпинского. Для квадрата находят середины его сторон. Эти точки
соединяются линиями, в результате чего образуется другой квадрат,
вписанный в первоначальный. К последующим квадратам применяется та
же процедура.
type
TRect = class(TForm)
procedure Rectangle(xa,ya,xb,yb,xc,yc,xd,yd,n:Integer);
procedure FormPaint(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Rect: TRect;
xa,ya,xb,yb,xc,yc,xd,yd,n,i,w: integer;
implementation
22
{$R *.dfm}
procedure TRect.Rectangle(xa,ya,xb,yb,xc,yc,xd,yd,n:integer);
var xp,yp,xr,yr,xq,yq,xf,yf: integer;
begin
if n>0 then begin
Rect.Canvas.Pen.Color:=clBlack;
xp:=(xa+xb) div 2; //нахождение середин сторон
yp:=(ya+yb) div 2;
xr:=(xb+xc) div 2;
yr:=(yb+yc) div 2;
xq:=(xc+xd) div 2;
yq:=(yc+yd) div 2;
xf:=(xa+xd) div 2;
yf:=(ya+yd) div 2;
Rect.Canvas.MoveTo(xp,yp);
Rect.Canvas.LineTo(xr,yr);
Rect.Canvas.MoveTo(xr,yr);
Rect.Canvas.LineTo(xq,yq);
Rect.Canvas.MoveTo(xq,yq);
Rect.Canvas.LineTo(xf,yf);
Rect.Canvas.MoveTo(xf,yf);
Rect.Canvas.LineTo(xp,yp);
Rectangle(xp,yp,xr,yr,xq,yq,xf,yf,n-1);
end;
end;
procedure TRect.FormPaint(Sender: TObject);
begin
Rect.Canvas.Pen.Width:=2;
xa:=0; ya:=500; //задание начальных значений
xb:=500; yb:=500;
xc:=500; yc:=50;
xd:=0; yd:=50;
Rectangle(xa,ya,xb,yb,xc,yc,xd,yd,n);
end;
Метод Описание
FillRect(const Rect: Заполняет текущей кистью прямоугольную область
TRect);* Rect, включая ее левую и верхнюю границу, но не
затрагивая правую и нижнюю границы.
MoveTo(x,y: Integer); Перемещает перо в положение (x,y) без вычерчивания
линий.
TextOut(x,y: integer; Выводит текстовую строку Text так, чтобы левый
const Text: String); верхний угол прямоугольника, охватывающего текст,
располагался в точке (х,у).
23
*Метод FillRect удобно использовать для удаления изображения. Нужно
просто задать цвет заливки таким же, как цвет формы и в скобках указать
всю область формы: Form1.Canvas.FillRect(Form1.ClientRect) ;
24
Листинг программы для построения кривой «Квадраты» в Visual Basic
25
Вы, наверное, часто видели довольно хитроумные картины, на которых
непонятно что изображено, но все равно необычность их форм завораживает
и приковывает внимание. Как правило, кажется, что эти хитроумные формы
не поддаются какому-либо математическому описанию. Однако такие
картины могут быть порождены многократным применением формулы,
связывающей каким-либо образом координаты x и у. Эти картины
называются аттракторами. Рассмотрим формулу, придуманную Мартином из
Астонского университета:
X n +1 = Yn − b ⋅ X n − c
Yn +1 = a − X n
procedure Tpoint.Paint;
var q,i,x,x1,y,a,b,c: integer;
begin
if n>0 then begin
s[0]:=clBlue; //каждому элементу массива задаем определенный цвет
s[1]:=clred;
s[2]:=clyellow;
s[3]:=clAqua;
s[4]:=clPurple;
s[5]:=clGreen;
26
s[6]:=clFuchsia;
s[7]:=clWhite;
repeat
Point.Canvas.MoveTo(x,y);
a:=StrToInt(Edit1.Text); //значения коэффициентов будут вводиться пользователем в
текстовые поля
b:=StrToInt(Edit2.Text);
c:=StrToInt(Edit3.Text);
for i:=1 to 1000 do
begin
for q:=0 to 7 do
begin
Point.Font.Color:=s[q];
p:=10; //искусственно вводим переменную для остановки цикла
x1:=x;
x:=trunc(y-sqrt(abs(b*x1-c)))-100;
y:=a-x1;
Point.Canvas.TextOut(x+300,y+100,'*');
end; end;
end;
until
p=10;
end;
end;
procedure Tpoint.FormPaint(Sender: TObject);
var q:integer;
begin
paint; //рисуем «звездное небо»
end;
Запустив программу и введя наугад три числа 33, 33 и 33, получим узор,
напоминающий цветок.
27
Числа 1, 1, 1000 дадут спираль.
28
Можно вводить любые числа и наблюдать за изменением узора. Особенно
интересные картины получаются, когда меняется одно из трех чисел, а
другие остаются без изменения. Можно добиться, чтобы узор распался в
«звездное небо» или выродился в несколько точек.
29