program MANDEL;
(*  compile this demo program from the command-line as
    DCC32 -u"LIB4D" MANDEL.DPR
    or open as a project in the Delphi IDE
    and add LIB4D to the search path in
    Project/Options

    Copyright 1996-2008 OptiCode - Dr. Martin Sander Software Dev.
*)

{$N+} {$D+}
uses VecLib, CMATH, WinProcs, Forms, ExtCtrls, StdCtrls;

{$ifdef VER180}   {Delphi10 / BDS 2006, RAD 2007}
       {$define Delphi10OrHigher}
{$endif}
const
   ProgName         = 'CMATH Mandelbrodt Demo';
   {$R *.DFM}
   (* Mandelbrodt parameters: *)
{$J+}
const  Offset:     fComplex = (Re: -0.5; Im: 0);
       Asymmetry:  fComplex = (Re: -0.06; Im: +0.015);
       zoom:       Single   = 1.0;
       maxit:      Uint     = 100;
    // play around with these values!

type
      TForm1 = class(TForm)
        PaintBox1: TPaintBox;
        BNextView: TButton;
        procedure ShowView(Sender: TObject);
        procedure NextView(Sender: TObject);
    end;

var
   Form1:                              TForm1;
type  ColorPalette  = array[0..15] of UInt;
const Colors: ColorPalette = ($00000000, $00800000,  $00008000,  $00000080,
                              $000000A0, $00808000,  $00800080,  $00808080,
                              $00B0B0B0, $00FF0000,  $0000FF00,  $000000FF,
                              $00FFFF00, $00FF00FF,  $0000FFFF,  $00FFFFFF);

procedure TForm1.NextView(Sender: TObject);
begin
       cf_mulRe( Asymmetry, Asymmetry, 2.0 );
            (* increase asymmetry; finally, too large asymmetry
               will destroy the picture  *)
       PaintBox1.Invalidate;
end;

procedure TForm1.ShowView(Sender: TObject);
var Colors: array [0..15] of UInt;
        (* set the Mandelbrodt parameters at the top of this file
          (below the "uses" statements)!
          A more advanced user interface would have to allow for live
          input of these parameters. For our purposes, setting them in
          in the source code has to be enough.  *)
    i, j, kk:            UInt;
    scal:                Single;
    ii, jj:              Integer;
    width_2, height_2:   UInt;
    CM, ZM:              fComplex;
begin
    width_2  := PaintBox1.Width div 2;
    height_2 := PaintBox1.Height div 2;
    scal     := 1.5 / zoom / height_2;
    for i := 0 to PaintBox1.Width-1 do
    begin
        ii := i - width_2;
        for j := 0 to PaintBox1.Height-1 do
        begin
            jj := j - height_2;
            {$ifdef Delphi10OrHigher}
                fcplx( ZM, ii, jj);
                ZM := ZM * scal + Offset;
                CM := ZM + Asymmetry;
            {$else} // older Delphi versions do not allow the simple operators
                    // However, the following, less readable version is much faster!
                fcplx( ZM, ii, jj);
                cf_mulRe( ZM, ZM, scal );
                cf_add( ZM, ZM, Offset );
                cf_add( CM, ZM, Asymmetry );
            {$endif}
            for kk := 0 to maxit-1 do
            begin    // iterate until |Z| > 2, or a maximum of maxit times
                     // iterative Mandelbrodt formula
                {$ifdef Delphi10OrHigher}
                    ZM := ZM*ZM + CM;
                    if abs(ZM) > 2.0 then break;
                {$else}
                    cf_square( ZM, ZM );
                    cf_add( ZM, ZM, CM );
                    if cf_abs( ZM ) > 2.0 then break;
                {$endif}
            end;  // kk now can be mapped to the plotting color
                  // for more details, use some nonlinear mapping function, like:
            Canvas.Pixels[i, j] := Colors[round(16*abs(sin( kk )))];
                 // even a completely different mapping function will still yield
                 // a similar picture, e.g. use the low bits of kk instead of the
                 // high bits as above:
             //  Canvas.Pixels[i, j] := Colors[round(16*abs(sin(kk mod 16)))];
        end;
    end;
end;

{$R *.RES}

begin
    Application.Initialize;
    Application.CreateForm(TForm1, Form1);
    Application.Run;
end.

