Следующая программа вычерчивает в диалоговом окне кривую Гильберта. На рис. 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 ������� ��������� ������
Помоги проекту! Расскажи друзьям об этом сайте: