КРИВЫЕ ГИЛЬБЕРТА
Этот узор состоит из суперпозиции пяти кривых. Три наложенные друг на друга кривые имеют форму Н1, Н2 и Н3.
Нi+1 получается соединением четырех экземпляров Нi вдвое меньшего размера, повернутых соответствующим образом и "стянутых" вместе тремя прямыми линиями. Н1 можно считать состоящей из четырех вхождений пустой Н0, соединенных этими же тремя линиями. Кривая Нi называется кривой Гильберта i-го порядка в честь ее первооткрывателя Д.Гильберта.
Каждая кривая Нi состоит из четырех вдвое меньших Нi-1 , то процедура для рисования Нi будет включать четыре обращения для рисования Нi-1, соответствующим образом повернутых и уменьшенных вдвое. Обозначим эти четыре части через А, В, С и D.
Это кривые Гильберта 1-го порядка.
Соединительные прямые будем обозначать стрелками, указывающими в соответствующем направлении. Будем предполагать, что направление задается целым параметром i как i·45 градусов.
Тогда получаем: при i=0, при i=2, при i=4, при i=6.
Для построения A, B, С, D получается следующая схема рекурсий:
A: D A A B
B: C B B A
C: B C C D
D: A D D C
Кривые Гильберта 2-го порядка.
Для рисования линии будем использовать процедуру :
Line( i, s: integer), где i - направление, s - длина отрезка.
procedure Line( i, s: integer);
BEGIN
x:=i*45/180*pi;
setlinestyle(0,0,1);
LineRel(Round(s*cos(x)),Round(s*sin(x)));
END;
Используя эту процедуру, с помощью рекурсивных обращений напишем процедуру, соответствующую схеме А:
Procedure A(i, s: integer);
BEGIN
if i>0 then
begin
D(i-1,s);
Line(4,s);
A(i-1,s);
Line(6,s);
A(i-1,s);
Line(0,s);
B(i-1,s);
end;
END;
Аналогично составляются процедуры для В, С, D. Процедура А инициируется главной программой по одному разу для каждой из кривых Гильберта. Главная программа определяет начальную точку кривой, т.е. исходные координаты (x0,y0) и начальное значение длины отрезка u (желательно, чтобы u=2n).
Эта программа рисует кривые Гильберта 5-го порядка.
Uses Crt, Graph;
Var
x :Real;
GrD, GrM :integer;
i,x0,y0,u :integer;
procedure Line( i, s: integer);
BEGIN
x:=i*45/180*pi;
setlinestyle(0,0,1);
LineRel(Round(s*cos(x)),Round(s*sin(x)));
END;
Procedure B(i, s: integer);forward;
Procedure C(i, s: integer);forward;
Procedure D(i, s: integer);forward;
Procedure A(i, s: integer);
BEGIN
if i>0 then
begin
D(i-1,s); Line(4,s);
A(i-1,s); Line(6,s);
A(i-1,s); Line(0,s);
B(i-1,s);
end;
END;
Procedure B;
BEGIN
if i>0 then
begin
C(i-1,s); Line(2,s);
B(i-1,s); Line(0,s);
B(i-1,s); Line(6,s);
A(i-1,s);
end;
END;
Procedure C;
BEGIN
if i>0 then
begin
B(i-1,s); Line(0,s);
C(i-1,s); Line(2,s);
C(i-1,s); Line(4,s);
D(i-1,s);
end;
END;
Procedure D;
BEGIN
if i>0 then
begin
A(i-1,s); Line(6,s);
D(i-1,s); Line(4,s);
D(i-1,s); Line(2,s);
C(i-1,s);
end;
END;
BEGIN {Кривые Гильберта Н1...Н5}
Grd := Detect;
InitGraph(GrD,GrM, ' путь драйвера ');
if GraphResult=GrOk
then
begin
x0:=450; y0:=350; u:=128; i:=1;
while i<=5 do
begin
MoveTo(x0,y0);
A(i,u); i:=i+1; u:=u div 2;
x0:=x0+(u div 2); y0:=y0+(u div 2);
Readln;
end;
CloseGraph;
end;
END.