Простой "квадратный" фрактал

6.jpg

Простой "квадратный" фрактал - частный случай фракталов из многоугольников. Конечная картинка представляет собой
совокупность квадратов с уменьшающимеся размерами. Центр каждого квадрата является вершиной какого-то квадрата.
Основная задача состоит в том, чтобы избежать построения квадратов, чьими центрами являются вершиный квадратов лежащие внутри уже построеных квадратов.

Алгоритм:
1. Создаём структуру , которая будет содержать координаты центров квадратов (Spoint).
2. По таймеру вызывается процедура Draw.
3. В процедуре Draw происходит рисование квадратов,центр которых - это точки, параметр draw которых равен true.
4. Увеличиваем счётчик num отвечающий за количество квадратов, которые будут построены на следующем шаге. num изменяется по степеням четвёрки.
5. В цикле “while k меньше num” добавляются вершины построеных квадратов в массив точек.При этом если вершины принадлежат квадратам,которые не были нарисованы, то добавляемая точка будет иметь в параметре draw значение false.
Рассмотрим значение flag.Оно изменяется от 1 до 4. Если flag=1, тогда центр построенного при данном вызове процедуры Draw квадрата - это левая верхняя вершина квадрата построенного при предыдущем вызове процедуры Draw, если flag=2 - правая верхняя, flag=3 - правая нижняя, flag=4 - левая нижняя.
6. При добавлении в массив точки, которая является ЛЕВОЙ ВЕРХНЕЙ вершиной квадрата, проверяем , построенли этот квадрат "вокруг" ПРАВОЙ НИЖНЕЙ вершины квадрата, строившегося на предыдущем шаге процедуры Draw.Если да (т.е. flag=3), то парметр draw у добавляемой точки принимает занчение false.
7. При добавлении в массив точки, которая является ПРАВОЙ ВЕРХНЕЙ вершиной квадрата, проверяем , построенли этот квадрат "вокруг" ЛЕВОЙ НИЖНЕЙ вершины квадрата, строившегося на предыдущем шаге процедуры Draw.Если да (т.е. flag=4), то парметр draw у добавляемой точки принимает занчение false.
8. При добавлении в массив точки, которая является ПРАВОЙ НИЖНЕЙ вершиной квадрата, проверяем , построенли этот квадрат "вокруг" ЛЕВОЙ ВЕРХНЕЙ вершины квадрата, строившегося на предыдущем шаге процедуры Draw.Если да (т.е. flag=1), то парметр draw у добавляемой точки принимает занчение false.
9. При добавлении в массив точки, которая является ЛЕВОЙ НИЖНЕЙ вершиной квадрата, проверяем , построенли этот квадрат "вокруг" ПРАВОЙ ВЕРХНЕЙ вершины квадрата, строившегося на предыдущем шаге процедуры Draw.Если да (т.е. flag=2), то парметр draw у добавляемой точки принимает занчение false.

unit Unit1; 
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,CRT,
  StdCtrls, ExtCtrls;
 
 
  const
	Min = 1;//Минимальный размер квадрата
type
 
  { TForm1 }
 
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    PaintBox1: TPaintBox;
    Timer1: TTimer;
 
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Draw(Sender: TObject) ;
    procedure PaintBox1DblClick(Sender: TObject);
 
  private
    { private declarations }
  public
    { public declarations }
  end; 
 
   type Spoint = record      //Структура данных для точек
    x,y: Double;
    draw : Boolean;
   end;
var
  Form1: TForm1; 
  size : real;
  num,i,j,k,t,flag : integer;
 
  a : array [1..66000] of Spoint;   //Массив точек
implementation
 
{ TForm1 }
 
procedure TForm1.Button1Click(Sender: TObject);
begin
  i:=1; //Номер последней точки, "вокруг" которой был построен квадрат
  j:=1; //Номер последней точки в массиве
  num:=1;//Количество точек, "вокруг" которых на данном шаге будут построены квадраты
  k:=1; //Счётчик количества построеных квадратов на данном шаге
  t:=1; //"Указатель" на точку, которая "пораждает" новые точки   (рассматриваемая точка)
  flag:=0;//Особый маркер
 
 
  a[1].draw:=true;
 
  a[1].x:=320;//
              //координаты первой точки массива
  a[1].y:=240;//
 
  size:=120;//Размер первого квадрата
 
 
  Timer1.Enabled:=true;
 
end;
 
procedure TForm1.Button2Click(Sender: TObject);
begin
 
  close;
end;
 
 
procedure TForm1.Draw(Sender: TObject);
begin
	if Size > Min then
	begin
            paintbox1.Canvas.Brush.Style:=bsclear;
               t:=i;
               for k:=1 to num do  begin        //постороение квадратов "вокруг" точек
                if a[i].draw=true then
        	paintbox1.canvas.Rectangle(Round(a[i].x - Size), Round(a[i].y - Size),Round(a[i].x + Size), Round(a[i].y + Size));
                i:=i+1;
               end;
               num:=num*4;
               j:=i;
               k:=1;
 
               while k<num do begin       // добавление новых точек в массив
                 if flag>4 then flag:=1;
 
 
 
 
 
       //На первом шаге в массив с точками добавляется левая верхняя вершина квадрата
                 a[ j ].x:= a[t].x - Size;
                 a[ j ].y:= a[t].y - Size;
                 a[ j ].draw:=true;
                 if a[t].draw=false then a[j].draw:=false;//если рассматриваемая точка пораждается точкой, "вокруг" которй не строился квадрат, то вокруг рассматриваемой точки также не строится квадрат (на последующих шагах повторяется данная проверка)
                 if flag=3 then   //если рассматриваемая вершина принадлежит квадрату, который построен "вокруг" ПРАВОЙ НИЖНЕЙ вершины другого квадрата,то "вокруг" рассматриваемой точки не нужно строить квадрат
                 if num>4 then
                    a[j].draw:=false;
 
 
       //На втором шаге в массив с точками добавляется правая верхняя вершина квадрата
                 a[j+1].x:= a[t].x + Size;
                 a[j+1].y:= a[t].y - Size;
                 a[j+1].draw:=true;
                 if a[t].draw=false then a[j+1].draw:=false;
                 if flag=4 then  //если рассматриваемая вершина принадлежит квадрату, который построен "вокруг" ЛЕВОЙ НИЖНЕЙ вершины другого квадрата,то "вокруг" рассматриваемой точки не нужно строить квадрат
                 if num>4 then
                    a[j+1].draw:=false;
 
 
 
       //На третьем шаге в массив с точками добавляется правая нижняя вершина квадрата
                 a[j+2].x:= a[t].x + Size;
                 a[j+2].y:= a[t].y + Size;
                 a[j+2].draw:=true;
                 if a[t].draw=false then a[j+2].draw:=false;
                 if flag=1 then  //если рассматриваемая вершина принадлежит квадрату, который построен "вокруг" ЛЕВОЙ ВЕРХНЕЙ вершины другого квадрата,то "вокруг" рассматриваемой точки не нужно строить квадрат
                 if num>4 then
                    a[j+2].draw:=false;
 
        //На четвёртом шаге в массив с точками добавляется левая нижняя вершина квадрата
                 a[j+3].x:= a[t].x - Size;
                 a[j+3].y:= a[t].y + Size;
                 a[j+3].draw:=true;
                 if a[t].draw=false then a[j+3].draw:=false;
                 if flag=2 then  //если рассматриваемая вершина принадлежит квадрату, который построен "вокруг" ПРАВОЙ ВЕРХНЕЙ вершины другого квадрата,то "вокруг" рассматриваемой точки не нужно строить квадрат
                 if num>4 then
                    a[j+3].draw:=false;
 
                 flag:=flag+1;
 
                 k:=k+4;
                 j:=j+4;
                 t:=t+1;
               end;
                 size := Size / 2;
 
 
	end;
      if  Size < Min  then
      Timer1.Enabled:=false;
 
end;
 
procedure TForm1.PaintBox1DblClick(Sender: TObject);
begin
  paintbox1.Refresh;
end;
 
 
 
initialization
  {$I unit1.lrs}
 
end.

Ключевые слова: 
Фрактальная графика . Фрактал из многоугольников
ВложениеРазмер
project1.rar1.86 Мб
UCXODHUK.rar1.48 кб