Delphi - база знаний

       

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


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





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.



Взято с сайта



Содержание раздела