Sources
Delphi Russian Knowledge Base
DRKB - это самая большая и удобная в использовании база знаний по Дельфи в рунете, составленная Виталием Невзоровым

Как нарисовать фрактал?

01.01.2007

clip0034

procedure DrawMandelbrot(ACanvas: TCanvas; X, Y, au, bu: Double; X2, Y2: Integer); 
var
  c1
, c2, z1, z2, tmp: Double;
  i
, j, Count: Integer;
begin
  c2
:= bu;
 
for i := 10 to X2 do  
 
begin
    c1
:= au;
   
for j := 0 to Y2 do  
   
begin
      z1
:= 0;
      z2
:= 0;
     
Count := 0;
     
{count is deep of iteration of the mandelbrot set
     
if |z| >=2 then z is not a member of a mandelset}
     
while (((z1 * z1 + z2 * z2 < 4) and (Count <= 90))) do  
     
begin
        tmp
:= z1;
        z1
:= z1 * z1 - z2 * z2 + c1;
        z2
:= 2 * tmp * z2 + c2;
       
Inc(Count);
     
end;
     
//the color-palette depends on TColor(n*count mod t)
     
{$IFDEF LINUX}
     
ACanvas.Pen.Color := (16 * Count mod 255);
     
ACanvas.DrawPoint(j, i);
     
{$ELSE}
     
ACanvas.Pixels[j, i] := (16 * Count mod 255);
     
{$ENDIF}
      c1
:= c1 + X;
   
end;
    c2
:= c2 + Y;
 
end;
end;
 
procedure TForm1
.Button1Click(Sender: TObject);
var
  R
: TRect;
  au
, ao: Integer;
  dX
, dY, bo, bu: Double;
begin
 
// Initialize Mandelbrot
  R
.Left := 0;
  R
.Right := 200;
  R
.Top := 0;
  R
.Bottom := 205;
  ao
:= 1;
  au
:= -2;
  bo
:= 1.5;
  bu
:= -1.5;
 
//direct scaling cause of speed
  dX
:= (ao - au) / (R.Right - R.Left);
  dY
:= (bo - bu) / (R.Bottom - R.Top);
 
DrawMandelbrot(Self.Canvas, dX, dY, au, bu, R.Right, R.Bottom);
end;

Автор: Михаил Марковский

...Очередная нетленка, которую я предлагаю Вам, написана мной самостоятельно (идею и примеры, реализованные в программе, я нашел в апрельском номере журнала "Химия и жизнь" за 1995 год). Теоретически она производит трансляцию L-систем с выводом образовавшихся фрактальных графов, а практически рисует кусты и деревья. Вроде бесполезно, но очень красиво. Эта программа написана для TP7, хотя легко переносится на Delphi (как то я уже переводил ее, но модуль бесследно исчез). Буду надеяться, что она придется Вам по душе.

uses graph, crt;
 
const
 
GrafType = 1; {1..3}
 
type
 
PointPtr = ^Point;
 
Point = record
    X
, Y: Word;
   
Angle: Real;
   
Next: PointPtr
 
end;
 
GrfLine = array[0..5000] of
   
Byte;
 
ChangeType = array[1..30] of
    record
   
Mean: Char;
   
NewString: string
 
end;
 
var
  K
, T, Dx, Dy, StepLength, GrafLength: Word;
  grDriver
, Xt: Integer;
  grMode
: Integer;
 
ErrCode: Integer;
 
CurPosition: Point;
 
Descript: GrfLine;
 
StartLine: string absolute Descript;
 
ChangeNumber, Generation: Byte;
 
Changes: ChangeType;
 
AngleStep: Real;
 
Mem: Pointer;
 
procedure
Replace(var Stroka: GrfLine;
 
OldChar: Char;
 
Repl: string);
var
  I
, J: Word;
begin
 
if (GrafLength = 0) or (Length(Repl) = 0) then
   
Exit;
  I
:= 1;
 
while I <= GrafLength do
 
begin
   
if Chr(Stroka[I]) = OldChar then
   
begin
     
for J := GrafLength downto I + 1 do
       
Stroka[J + Length(Repl) - 1] := Stroka[J];
     
for J := 1 to Length(Repl) do
       
Stroka[I + J - 1] := Ord(Repl[J]);
      I
:= I + J;
     
GrafLength := GrafLength + Length(Repl) - 1;
     
continue
   
end;
    I
:= I + 1
 
end
end;
 
procedure
PushCoord(var Ptr: PointPtr;
 
  C
: Point);
var
 
  P
: PointPtr;
begin
 
 
New(P);
  P
^.X := C.X;
  P
^.Y := C.Y;
  P
^.Angle := C.Angle;
  P
^.Next := Ptr;
 
Ptr := P
end;
 
procedure
PopCoord(var Ptr: PointPtr;
 
 
var Res: Point);
begin
 
 
if Ptr <> nil then
 
begin
   
Res.X := Ptr^.X;
   
Res.Y := Ptr^.Y;
   
Res.Angle := Ptr^.Angle;
   
Ptr := Ptr^.Next
 
end
end;
 
procedure
FindGrafCoord(var Dx, Dy: Word;
 
 
Angle: Real;
 
StepLength: Word);
begin
 
 
Dx := Round(Sin(Angle) * StepLength * GetMaxX / GetMaxY);
 
Dy := Round(-Cos(Angle) * StepLength);
end;
 
procedure
NewAngle(Way: ShortInt;
 
 
var Angle: Real;
 
AngleStep: Real);
begin
 
 
if Way >= 0 then
   
Angle := Angle + AngleStep
 
else
   
Angle := Angle - AngleStep;
 
if Angle >= 4 * Pi then
   
Angle := Angle - 4 * Pi;
 
if Angle < 0 then
   
Angle := 4 * Pi + Angle
end;
 
procedure
Rost(var Descr: GrfLine;
 
 
Cn: Byte;
 
Ch: ChangeType);
var
  I
: Byte;
begin
 
 
for I := 1 to Cn do
   
Replace(Descr, Ch[I].Mean, Ch[I].NewString);
end;
 
procedure Init1
;
begin
 
 
AngleStep := Pi / 8;
 
StepLength := 7;
 
Generation := 4;
 
ChangeNumber := 1;
 
CurPosition.Next := nil;
 
StartLine := 'F';
 
GrafLength := Length(StartLine);
 
with Changes[1] do
 
begin
   
Mean := 'F';
   
NewString := 'FF+[+F-F-F]-[-F+F+F]'
 
end;
end;
 
procedure Init2
;
begin
 
 
AngleStep := Pi / 4;
 
StepLength := 3;
 
Generation := 5;
 
ChangeNumber := 2;
 
CurPosition.Next := nil;
 
StartLine := 'G';
 
GrafLength := Length(StartLine);
 
with Changes[1] do
 
begin
   
Mean := 'G';
   
NewString := 'GFX[+G][-G]'
 
end;
 
with Changes[2] do
 
begin
   
Mean := 'X';
   
NewString := 'X[-FFF][+FFF]FX'
 
end;
end;
 
procedure Init3
;
begin
 
 
AngleStep := Pi / 10;
 
StepLength := 9;
 
Generation := 5;
 
ChangeNumber := 5;
 
CurPosition.Next := nil;
 
StartLine := 'SLFF';
 
GrafLength := Length(StartLine);
 
with Changes[1] do
 
begin
   
Mean := 'S';
   
NewString := '[+++G][---G]TS'
 
end;
 
with Changes[2] do
 
begin
   
Mean := 'G';
   
NewString := '+H[-G]L'
 
end;
 
with Changes[3] do
 
begin
   
Mean := 'H';
   
NewString := '-G[+H]L'
 
end;
 
with Changes[4] do
 
begin
   
Mean := 'T';
   
NewString := 'TL'
 
end;
 
with Changes[5] do
 
begin
   
Mean := 'L';
   
NewString := '[-FFF][+FFF]F'
 
end;
end;
 
begin
 
 
case GrafType of
   
1: Init1;
   
2: Init2;
   
3: Init3;
 
else
 
end;
  grDriver
:= detect;
 
InitGraph(grDriver, grMode, '');
 
ErrCode := GraphResult;
 
if ErrCode <> grOk then
 
begin
   
WriteLn('Graphics error:', GraphErrorMsg(ErrCode));
   
Halt(1)
 
end;
 
with CurPosition do
 
begin
    X
:= GetMaxX div 2;
    Y
:= GetMaxY;
   
Angle := 0;
   
MoveTo(X, Y)
 
end;
 
SetColor(white);
 
for K := 1 to Generation do
 
begin
   
Rost(Descript, ChangeNumber, Changes);
   
Mark(Mem);
   
for T := 1 to GrafLength do
   
begin
     
case Chr(Descript[T]) of
       
'F':
         
begin
           
FindGrafCoord(Dx, Dy, CurPosition.Angle, StepLength);
           
with CurPosition do
           
begin
             
Xt := X + Dx;
             
if Xt < 0 then
                X
:= 0
             
else
                X
:= Xt;
             
if X > GetMaxX then
                X
:= GetMaxX;
             
Xt := Y + Dy;
             
if Xt < 0 then
                Y
:= 0
             
else
                Y
:= Xt;
             
if Y > GetMaxY then
                Y
:= GetMaxY;
             
LineTo(X, Y)
           
end
         
end;
       
'f':
         
begin
           
FindGrafCoord(Dx, Dy, CurPosition.Angle, StepLength);
           
with CurPosition do
           
begin
             
Xt := X + Dx;
             
if Xt < 0 then
                X
:= 0
             
else
                X
:= Xt;
             
if X > GetMaxX then
                X
:= GetMaxX;
             
Xt := Y + Dy;
             
if Xt < 0 then
                Y
:= 0
             
else
                Y
:= Xt;
             
if Y > GetMaxY then
                Y
:= GetMaxY;
             
MoveTo(X, Y)
           
end
         
end;
       
'+': NewAngle(1, CurPosition.Angle, AngleStep);
       
'-': NewAngle(-1, CurPosition.Angle, AngleStep);
       
'I': NewAngle(1, CurPosition.Angle, 2 * Pi);
       
'[': PushCoord(CurPosition.Next, CurPosition);
       
']':
         
begin
           
PopCoord(CurPosition.Next, CurPosition);
           
with CurPosition do
             
MoveTo(X, Y)
         
end
     
end
   
end;
   
Dispose(Mem);
   
Delay(1000)
 
end;
  repeat
 
until KeyPressed;
 
CloseGraph
end.

Взято с сайта https://www.swissdelphicenter.ch/en/tipsindex.php