Кривые Гильберта

На рис. 3.2 приведен пример кривых Гильберта.

Рис. 3.2. Кривые Гильберта

Этот узор состоит из суперпозиции пяти кривых. Три наложенные друг на друга кривые имеют форму Н1, Н2 и Н3 (см. рис. 3.3.)

Рис. 3.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.