マンデルブロ集合

 フラクタルのMandelbrotプログラムで、複素数を使用したプログラムです。
https://codes-sources.commentcamarche.net/source/22471-fractal-de-mandelbrot から ダウンロードし、修正したものです。

 表示画像の切り替えは、左上のアイコンをマウスでクリックするとメニューが表示されるので、選択してください。
画像は、五種類ほどあります。
部分拡大表示が出来ます、拡大する範囲をマウスで選択してください、元の大きさに戻す場合は、画像部を単にクリックするか、左下から右上に範囲をしていします。

プログラム

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Unit_Complexe, ActnList, Menus, ExtDlgs, ExtCtrls, System.Actions,
  system.Types, system.UITypes;

type
  TPointFloat = record
    x, y : Extended;
    Ex, Ey : Integer;
  end;

type
  TForm1 = class(TForm)
    Image1: TImage;
    procedure FermerExecute(Sender: TObject);
    procedure TracerExecute(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Image1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure Image1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    Debut, Fin : TPointFloat;
    PrecDebut, PrecFin : TPointFloat;
    R, PrecR, RapportReel : Extended;
    Longueur, Hauteur : Extended;
    Deplacement : Boolean;
    Origine, Move : TPoint;
    select: integer;
    OutputBitmap  : TBitmap;
    procedure Initialize;
    procedure Effacer;
    procedure AddMenu;
    Procedure WMSysCommand(var msg: TWMSysCommand);message WM_SysCommand;
  public

  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

type
  TPrgbarry = array[0..0] of Trgbtriple;  // 24ビットカラーレコード 32ビット用はTRGBQuadArray
  Prgbarray = ^TPrgbarry;                 // ポインター

procedure TForm1.WMSysCommand(var msg: TWMSysCommand);
begin
  case Msg.CmdType and $FFof
    10: begin select := 0; Initialize; TracerExecute(nil); end;
    11: begin select := 1; Initialize; TracerExecute(nil); end;
    12: begin select := 2; Initialize; TracerExecute(nil); end;
    13: begin select := 3; Initialize; TracerExecute(nil); end;
    14: begin select := 4; Initialize; TracerExecute(nil); end;
  end;
  inherited;
end;

procedure TForm1.AddMenu;
var
  hSysMenu:integer;
begin
  hSysMenu := GetSystemMenu(Handle,False);
    // 底に(最後に)追加する
    // セパレータを追加
  AppendMenu(hSysMenu, MF_SEPARATOR,0,nil);
    // 'NewMenuを追加
  AppendMenu(hSysMenu, MF_STRING, 10, 'Menu_1');
  AppendMenu(hSysMenu, MF_STRING, 11, 'Menu_2');
  AppendMenu(hSysMenu, MF_STRING, 12, 'Menu_3');
  AppendMenu(hSysMenu, MF_STRING, 13, 'Menu_4');
  AppendMenu(hSysMenu, MF_STRING, 14, 'Menu_5');
end;

procedure TForm1.FermerExecute(Sender: TObject);
begin
  Close;
end;

procedure TForm1.TracerExecute(Sender: TObject);
var
  Couleur         : Byte;
  Module          : Double;
  IndexX, IndexY  : Integer;
  Taille          : Integer;
  X, Y            : Extended;
  W2, h2          : integer;
  PBA             : Prgbarray;            // RGBtriple配列のポインター
begin
  Effacer;
  Taille := 250;
  case select of
    0, 4: c := Complexe.Create(0, 0);
    1: c := Complexe.Create(-0.0986, -0.65186);
    2: c := Complexe.Create(-0.772691322542185, 0.124281466072787);
    3: c := Complexe.Create(-0.3380, 0.6230);
  end;
  i := Complexe.Create(0, 0);
  z := Complexe.Create(0, 0);
  W2 := image1.Width div 2;
  if (select = 0) or (select = 4) then W2 := W2 + 150;
  H2 := image1.Height div 2;
  for IndexY := 0 to image1.Height - 1 do
  begin
    PBA := OutputBitmap.ScanLine[IndexY];
    for IndexX := 0 to image1.Width - 1 do
    begin
      X := Debut.x + IndexX / RapportReel - W2;
      Y := Debut.y + IndexY / RapportReel - H2;
      z.Re := X / Taille;
      z.Im := Y / Taille;
      if (select = 0) or (select = 4) then
      begin
        c.Re := X / Taille;
        c.Im := Y / Taille;
      end;
      Module := 0;
      Couleur := 0;
      repeat
        z.Polynome(z, 2);
        z.Addition(z, c);
        Module := z.Module;
        inc(Couleur, 1);
        if select = 4 then begin
          if Couleur = 60 then Break;
        end
        else
          if Couleur = 0 then Break;
      until Module >= 4;
      if select = 4 then Couleur := 16 * Couleur mod 256;
      case select of
        0: begin PBA[indexX].rgbtRed := 0; PBA[indexX].rgbtGreen := Couleur; PBA[indexX].rgbtBlue := Couleur; end;
        1: begin PBA[indexX].rgbtRed := Couleur; PBA[indexX].rgbtGreen := 0; PBA[indexX].rgbtBlue := Couleur; end;
        2: begin PBA[indexX].rgbtRed := Couleur; PBA[indexX].rgbtGreen := Couleur; PBA[indexX].rgbtBlue := 0; end;
        3: begin PBA[indexX].rgbtRed := Couleur; PBA[indexX].rgbtGreen := Couleur; PBA[indexX].rgbtBlue := Couleur; end;
        4: begin PBA[indexX].rgbtRed := Couleur; PBA[indexX].rgbtGreen := 0; PBA[indexX].rgbtBlue := 0; end;
      end;
    end;
  end;
  image1.Picture.Bitmap := OutputBitmap;
  FreeAndNil(i);
  FreeAndNil(c);
  FreeAndNil(z);
end;

procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  PrecDebut := Debut;
  PrecFin := Fin;

  Longueur := PrecFin.x - PrecDebut.x;
  Hauteur := PrecFin.y - PrecDebut.y;

  Debut.Ex := X;
  Debut.Ey := Y;
  Debut.x := Longueur / Image1.Width * Debut.Ex + PrecDebut.x;
  Debut.y := Hauteur / Image1.Height * Debut.Ey + PrecDebut.y;

  Deplacement := True;
  Origine := Point(X, Y);
  Move := Origine;
end;

procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
  Rapport : Double;
begin
  if Deplacement then
  begin
    Rapport := Image1.Height / Image1.Width;
    Image1.Canvas.Pen.Style := psDot;
    Image1.Canvas.Pen.Mode := pmNotXor;
    Image1.Canvas.Rectangle(Origine.x, Origine.y, Move.x, Origine.y + Round((Move.x - Origine.x) * Rapport));
    Move := Point(X, Y);
    Image1.Canvas.Rectangle(Origine.x, Origine.y, Move.x, Origine.y + Round((Move.x - Origine.x) * Rapport));
  end;
end;

procedure TForm1.Image1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  Image1.Canvas.Pen.Mode := pmCopy;

  Deplacement := False;

  Fin.Ex := X;
  Fin.Ey := Y;

  if Fin.Ex - Debut.Ex <= 0 then
  begin
    Initialize;
  end
  else
  begin
    PrecR := RapportReel;
    R := Image1.Width/(Fin.Ex - Debut.Ex);
    RapportReel := R*PrecR;

    Fin.x := Debut.x + Longueur/R;
    Fin.y := Debut.y + Hauteur/R;
  end;
  TracerExecute(Sender);
end;

procedure TForm1.Initialize;
begin
  { On initialise les variables }
  Debut.x := 0;
  Debut.y := 0;
  Debut.Ex := 0;
  Debut.Ey := 0;

  Fin.x := image1.Width;
  Fin.y := image1.Height;
  Fin.Ex := image1.Width;
  Fin.Ey := image1.Height;

  PrecDebut := Debut;
  PrecFin := Fin;

  PrecR := 1;
  R := 1;
  RapportReel := R*PrecR;

  Longueur := image1.Width;
  Hauteur := image1.Height;

  Deplacement := False;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  OutputBitmap.Free;      // bitmapの開放
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Width := 1024;
  Height := 700;
  Top := (Screen.Height - Height) div 2;
  Left := (Screen.Width - Width) div 2;
  AddMenu;
  select := 0;
  Initialize;
  OutputBitmap  := TBitmap.Create;
  OutputBitmap.PixelFormat := pf24bit;
  OutputBitmap.Height := Image1.Height;
  OutputBitmap.Width := Image1.Width;
  TracerExecute(Sender);
end;

procedure TForm1.Effacer;
var
  ColorPen, ColorBrush : TColor;
begin
  ColorPen := Image1.Canvas.Pen.Color;
  ColorBrush := Image1.Canvas.Brush.Color;
  with Image1.Canvas do begin
    Pen.Style := psSolid;
    Pen.Color := clBtnFace;
    Brush.Color := clBtnFace;
    Rectangle(0, 0, Width, Height);
    Font.Color := clBlack;
    Font.Size := 30;
    TextOut(100,50, 'S''il vous plaît');
    TextOut(100,150, 'Wait a moment');
    Pen.Color := ColorPen;
    Brush.Color := ColorBrush;
  end;
  application.ProcessMessages;
end;

end.

 

unit Unit_Complexe;

interface

uses
  Sysutils, Math, classes;

type
  Complexe = class
  protected
    FRe : Extended;
    FIm : Extended;
  private
  public
    constructor Create(Re, Im : Extended);
    procedure Addition(Result, C2 : Complexe);
    procedure Multiplication(Result, C2 : Complexe);
    function Module : Extended;
    procedure Polynome(Result : Complexe; Degree : Integer);
    property Re : Extended Read FRe Write FRe;
    property Im : Extended Read FIm Write FIm;
end;

var
  i, c, z : Complexe;

implementation

{ Complexe }

constructor Complexe.Create(Re, Im: Extended);
begin
  FRe := Re;
  FIm := Im;
end;

procedure Complexe.Addition(Result, C2: Complexe);
begin
  Result.Re := Self.Re + C2.Re;
  Result.Im := Self.Im + C2.Im;
end;

procedure Complexe.Multiplication(Result, C2: Complexe);
begin
  Result.Re := Self.Re * C2.Re - Self.Im * C2.Im;
  Result.Im := Self.Re * C2.Im + Self.Im * C2.Re;
end;

function Complexe.Module: Extended;
begin
  Result := Sqr(Self.Re) + Sqr(Self.Im);
end;

procedure Complexe.Polynome(Result : Complexe; Degree : Integer);
var
  Index : Integer;
  Reelle, Imaginaire : Extended;
begin
  Result.Re := Self.Re;
  Result.Im := Self.Im;
  i.Re := Self.Re;
  i.Im := Self.Im;
  for Index := 2 to Degree do
  begin
    Reelle := Result.Re * i.Re - Result.Im * i.Im;
    Imaginaire := Result.Re * i.Im + Result.Im * i.Re;
    Result.Re := Reelle;
    Result.Im := Imaginaire;
  end;
end;

end.


download MandelbrotNo2Image.zip

  画像処理プログラム 作図 に戻る