Следующая программа вычерчивает в диалоговом окне кривую Гильберта. На рис. 12.7 приведены кривые Гильберта первого, второго и третьего порядков. Если присмотреться, то видно, что кривая второго порядка получается путем соединения прямыми линиями четырех кривых первого порядка. Аналогичным образом получается кривая третьего порядка, но при этом в качестве "кирпичиков" используются кривые второго порядка. Таким образом, чтобы нарисовать кривую третьего порядка, надо нарисовать четыре кривых второго порядка. В свою очередь, чтобы нарисовать кривую второго порядка, надо нарисовать четыре кривых первого порядка. Таким образом, алгоритм вычерчивания кривой Гильберта является рекурсивным.
Диалоговое окно программы Кривая Гильберта, в котором находится кривая пятого порядка, приведено на рис. 12.8, текст программы — в листинге 12.4.
Рис. 12.7. Кривые Гильберта первого, второго и третьего порядков
Кривые первого порядка получаются путем соединения кривых нулевого порядка (точек)

Кривая второго порядка (а2| образуется путем соединения четырех кривых первого порядка (элементов d, а. а и с)

Кривая третьего порядка получается путем соединения кривых d, a, a и с второго порядка

Рис. 12.8. Кривая Гильберта пятого порядка

Листинг 12.4. Кривая Гильберта
01.unit gilbert_;
02.interface
03.uses
04.Windows, Messages, SysUtils, Variants, Classes, Graphics,
05.Controls, Forms, Dialogs, StdCtrls, ComCtrls;
06.type
07.TForrnl = class(TForm)
08.procedure ForraPaint(Sender: TObj ect);
09.private
10.
11.public
12.
13.end;
14.var
15.Forml: TForml;
16.implementation
17.{$R *.dfm)
18.var
19.p: integer =5;
20.u: integer = 7;
21.l Кривую Гильберта можно получить путем соединения элементов а,Ь,с и d.
22.Каждый элемент строит соответствующая процедура. )
23.procedure a(i:integer; canvas: TCanvas); forward;
24.procedure b(i:integer; canvas: TCanvas); forward;
25.procedure c(i:integer; canvas: TCanvas]; forward;
26.procedure d(i:integer; canvas: TCanvas]; forward;
27.
28.procedure a(i: integer; canvas: TCanvas);
29.begin
30.if i > 0 then begin
31.d(i-l, canvas); canvas.LineTo(canvas.PenPos.X+u,canvas.PenPos.Y);
32.a(i-l, canvas); canvas.LineTo(canvas.PenPos.X,canvas.PenPos.Y+u);
33.a(i-l, canvas); canvas.LineTo(canvas.PenPos.X-u,canvas.PenPos.Y);
34.c(i-l, canvas);
35.end;
36.end;
37.procedure b (i: integer; canvas: TCanvas);
38.begin
39.if i > 0 then
40.begin
41.c(i-l, canvas); canvas.LineTo(canvas.PenPos.X-u,canvas.PenPos.Y];
42.b(i-l, canvas); canvas.LineTo(canvas.PenPos.X,canvas.PenPos.Y-u];
43.b(i-l, canvas); canvas .LineTo(canvas. PenPos.X-t-u,canvas.PenPos.Y);
44.d(i-l, canvas);
45.end;
46.end;
47.procedure c(i: integer; canvas: TCanvas);
48.begin
49.if i > 0 then
50.begin
51.b(i-l, canvas); canvas.LineTo(canvas.PenPos.X,canvas.PenPos.Y-u);
52.c(i-l, canvas); canvas.LineTo(canvas.PenPos.X-u,canvas.PenPos.Y);
53.c(i-l, canvas); canvas.LineToicanvas.PenPos.X,canvas.PenPos.Y+u);
54.a (i-1, canvas);
55.end;
56.end;
57.procedure d(i: integer; canvas: TCanvas);
58.begin
59.if i > 0 then
60.begin
61.a (i-1, canvas); canvas.LineTo(canvas.PenPos.X,canvas.PenPos.Y+u);
62.d(i-l, canvas); canvas.LineTo(canvas.PenPos.X+u,canvas.PenPos.Y);
63.d(i-l, canvas); canvas.LineTo(canvas.PenPos.X,canvas.PenPos.Y-u);
64.b(i-l, canvas);
65.end;
66.end;
67.procedure TForml.FormPaintfSender: TObject);
68.begin
69.Forral.Canvas.MoveTo(u,u);
70.a[5,Forml.Canvas);
71.end;
72.end.
Следует обратить внимание на следующую особенность реализации программы. Процедура, которая вычерчивает элемент а, помимо самой себя (для вычерчивания элемента а кривой более низкого порядка) вызывает процедуры d и ь, описание (текст) которых в тексте программы находится после процедуры а. Чтобы компилятор не вывел сообщение об ошибке, в текст программы помещено объявление процедуры с ключевым словом forward, означающим, что это только объявление, а описание (реализация) находится дальше. Таким образом, уже в процессе компиляции процедуры а, компилятор "знает", что имена ь и d означают процедуры.
������� ������ ��� dle ������� ��������� ������
Помоги проекту! Расскажи друзьям об этом сайте: