Feature: function generation added to GUI

This commit is contained in:
KoroLion 2020-05-22 18:18:34 +03:00
parent 1f4577657e
commit c55277b590
9 changed files with 179 additions and 98 deletions

2
.gitignore vendored
View File

@ -1,3 +1,5 @@
images/*
*.o
*.ppu
*.exe

View File

@ -1,9 +1,15 @@
rm generator.exe
rm multibrot_imaging.exe
rm function_imaging.exe
rm gui.exe
cd src
fpc mandelbrot_imaging.pas
mv mandelbrot_imaging.exe ../generator.exe
mv mandelbrot_imaging.exe ../multibrot_imaging.exe
fpc function_imaging.pas
mv function_imaging.exe ../function_imaging.exe
cd gui
fpc gui.pas
mv gui.exe ../../gui.exe

1
multibrot_images/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*.bmp

View File

@ -106,6 +106,7 @@ begin
pxData[x][y].set_color(255, 255, 255);
end;
end else begin
fParser.expression := stringReplace(fParser.expression, '=', '-', []);
fRes1 := fParser.evaluate().resFloat;
// finding derivative of a function at this point (numeric)

View File

@ -2,7 +2,10 @@ unit constants;
interface
const cmAbout = 1001;
const cmGenerate = 1002;
const cmMbGenerate = 1002;
const cmFnGenerate = 1003;
const cmMbNew = 1004;
const cmFnNew = 1005;
implementation
end.

View File

@ -4,8 +4,8 @@ uses
utils, constants;
type
PGenerateData = ^TGenerateData;
TGenerateData = record
PMbGenerateData = ^TMbGenerateData;
TMbGenerateData = record
path: string[128];
width: string[16];
height: string[16];
@ -15,46 +15,72 @@ type
centerY: string[64];
end;
PFnGenerateData = ^TFnGenerateData;
TFnGenerateData = record
path: string[128];
width: string[16];
height: string[16];
fn: string[255];
zoom: string[64];
centerX: string[64];
centerY: string[64];
end;
PGeneratorWindow = ^TGeneratorWindow;
TGeneratorWindow = object(TDialog)
pGeneratingBtn: PButton;
winRect: TRect;
curY: integer;
constructor Init;
procedure addField(caption: string; maxLength: integer);
function addButton(caption: string; command: integer): PButton;
end;
PMbGeneratorWindow = ^TMbGeneratorWindow;
TMbGeneratorWindow = object(TGeneratorWindow)
constructor Init;
end;
PFnGeneratorWindow = ^TFnGeneratorWindow;
TFnGeneratorWindow = object(TGeneratorWindow)
constructor Init;
end;
TMSApp = object(TApplication)
GeneratorWindow: PGeneratorWindow;
MbGeneratorWindow: PMbGeneratorWindow;
FnGeneratorWindow: PFnGeneratorWindow;
procedure InitStatusLine; virtual;
procedure InitMenuBar; virtual;
procedure HandleEvent(var Event: TEvent); virtual;
procedure NewWindow();
procedure GenerateMandelbrotSetImage();
procedure NewMbWindow();
procedure NewFnWindow();
procedure GenerateMultibrotSetImage();
procedure GenerateFunctionImage();
procedure ShowAbout();
procedure ShowSuccess(fname: string; t: extended);
end;
var
MSApp: TMSApp;
GenerateData: TGenerateData;
MbGenerateData: TMbGenerateData;
FnGenerateData: TFnGenerateData;
procedure TMSApp.GenerateMandelbrotSetImage();
procedure TMSApp.GenerateMultibrotSetImage();
var
s: AnsiString;
startTime: int64;
success: boolean;
begin
GeneratorWindow^.GetData(GenerateData);
MbGeneratorWindow^.GetData(MbGenerateData);
startTime := getTimestamp();
GeneratorWindow^.pGeneratingBtn^.show();
with GenerateData do begin
success := RunCommand('./generator', [
MbGeneratorWindow^.pGeneratingBtn^.show();
with MbGenerateData do begin
success := RunCommand('./multibrot_imaging', [
width,
height,
power,
@ -64,7 +90,42 @@ begin
path
], s);
end;
GeneratorWindow^.pGeneratingBtn^.hide();
MbGeneratorWindow^.pGeneratingBtn^.hide();
if (success) then begin
ShowSuccess(s, (getTimestamp() - startTime) / 1000);
end else begin
MessageBox(
#3'Error'#13 +
#3'Unable to execute generator!'#13,
nil,
mfInformation or mfOkButton
);
end;
end;
procedure TMSApp.GenerateFunctionImage();
var
s: AnsiString;
startTime: int64;
success: boolean;
begin
FnGeneratorWindow^.GetData(FnGenerateData);
startTime := getTimestamp();
FnGeneratorWindow^.pGeneratingBtn^.show();
with FnGenerateData do begin
success := RunCommand('./function_imaging', [
width,
height,
fn,
zoom,
centerX,
centerY,
path
], s);
end;
FnGeneratorWindow^.pGeneratingBtn^.hide();
if (success) then begin
ShowSuccess(s, (getTimestamp() - startTime) / 1000);
@ -108,20 +169,20 @@ begin
addButton := pbtn;
end;
constructor TGeneratorWindow.Init();
constructor TMbGeneratorWindow.Init();
var
r: TRect;
begin
r.assign(0, 0, 60, 19);
inherited Init(r, 'Mandelbrot generator');
inherited Init(r, 'Multibrot generator');
Options := Options or ofCentered;
HelpCtx := $F000;
winRect := r;
curY := 2;
with GenerateData do begin
path := './generated_images';
with MbGenerateData do begin
path := './multibrot_images';
width := '512';
height := '512';
power := '2';
@ -138,17 +199,60 @@ begin
addField('Center X:', 64);
addField('Center Y:', 64);
addButton('Generate', cmGenerate);
addButton('Generate', cmMbGenerate);
curY := curY - 2;
pGeneratingBtn := addButton('Generating...', 0);
pGeneratingBtn^.hide();
end;
procedure TMSApp.NewWindow();
constructor TFnGeneratorWindow.Init();
var
r: TRect;
begin
GeneratorWindow := New(PGeneratorWindow, Init);
GeneratorWindow^.SetData(GenerateData);
InsertWindow(GeneratorWindow);
r.assign(0, 0, 60, 19);
inherited Init(r, 'Function generator');
Options := Options or ofCentered;
HelpCtx := $F000;
winRect := r;
curY := 2;
with FnGenerateData do begin
path := './function_images';
width := '512';
height := '512';
fn := 'sin(x*x*x * y*y) = cos(x*x * y*y*y)';
zoom := '10';
centerX := '0';
centerY := '0';
end;
addField('Path:', 128);
addField('Width:', 16);
addField('Height:', 16);
addField('Function:', 255);
addField('Zoom:', 64);
addField('Center X:', 64);
addField('Center Y:', 64);
addButton('Generate', cmFnGenerate);
curY := curY - 2;
pGeneratingBtn := addButton('Generating...', 0);
pGeneratingBtn^.hide();
end;
procedure TMSApp.NewFnWindow();
begin
FnGeneratorWindow := New(PFnGeneratorWindow, Init);
FnGeneratorWindow^.SetData(FnGenerateData);
InsertWindow(FnGeneratorWindow);
end;
procedure TMSApp.NewMbWindow();
begin
MbGeneratorWindow := New(PMbGeneratorWindow, Init);
MbGeneratorWindow^.SetData(MbGenerateData);
InsertWindow(MbGeneratorWindow);
end;
procedure TMSApp.ShowAbout();
@ -165,7 +269,7 @@ end;
procedure TMSApp.ShowSuccess(fname: string; t: extended);
begin
MessageBox(
#3'Set image was generated!'#13 +
#3'Image was generated!'#13 +
'File name: ' + fname + #13 +
'Time spent: ' + FloatToStr(t) + ' s',
nil,
@ -179,16 +283,24 @@ begin
if Event.What = evCommand then begin
case Event.Command of
cmNew: begin
NewWindow();
cmMbNew: begin
NewMbWindow();
ClearEvent(Event);
end;
cmFnNew: begin
NewFnWindow();
ClearEvent(Event);
end;
cmAbout: begin
ShowAbout();
ClearEvent(Event);
end;
cmGenerate: begin
GenerateMandelbrotSetImage();
cmMbGenerate: begin
GenerateMultibrotSetImage();
ClearEvent(Event);
end;
cmFnGenerate: begin
GenerateFunctionImage();
ClearEvent(Event);
end;
end;
@ -204,7 +316,7 @@ begin
New(StatusLine, Init(r,
NewStatusDef(0, $EFFF,
NewStatusKey('~Alt+X~ Exit', kbAltX, cmQuit,
NewStatusKey('~F3~ New', kbF3, cmNew,
NewStatusKey('~F3~ New', kbF3, cmMbNew,
nil
)), nil)
));
@ -217,10 +329,11 @@ begin
GetExtent(r);
r.b.y := r.a.y + 1;
MenuBar := New(PMenuBar, Init(r, NewMenu(
NewItem('~M~andelbrot', '', kbNoKey, cmNew, hcNew,
NewItem('~M~ultibrot', '', kbNoKey, cmMbNew, hcNew,
NewItem('~F~unctions', '', kbNoKey, cmFnNew, hcNew,
NewItem('~A~bout', '', kbNoKey, cmAbout, hcNoContext,
NewItem('~E~xit', 'Alt+X', kbAltX, cmQuit, hcExit,
nil)))))
nil))))))
);
end;

View File

@ -1,10 +1,14 @@
uses sysutils, BMPImage, ucomplex, utils;
// todo: generalize get_filename function
// todo: camelCase
// todo: multibrot fraction power
type
TArgs = record
power: longint;
width: longint; // TryStrToInt wants longint
height: longint;
power: longint;
zoom: extended;
center_x: extended;
center_y: extended;
@ -12,23 +16,24 @@ type
end;
const save_path = './images/generated/';
const help_text = 'Usage: command <width = 512> <height = 512> <power = 2> <zoom = 1> <centerX = 0> <centerY = 0> <out_path = ./images>';
const help_text = 'Usage: command <power = 2> <width = 512> <height = 512> <zoom = 1> <centerX = 0> <centerY = 0> <out_path = ./multibrot_images>';
{function f(x: integer): integer;
function get_filename(base_name: string; zoom: extended; center_x: extended; center_y: extended): string;
var
z, cx, cy: string;
begin
z := FloatToStr(zoom);
cx := FloatToStr(center_x);
cy := FloatToStr(center_y);
get_filename := base_name + '_(z=' + z + ';cx=' + cx + ';cy=' + cy + ').bmp'
end;
function f(x: integer): integer;
begin
f := round(2 * sin(x) + 3);
end;
function check_a(x: integer; y: integer): boolean;
begin
check_a := sqr(x - 50) + sqr(y - 50) - 6 <= 900;
end;
function fr(x: integer; c: integer): integer;
begin
fr := sqr(x) + c;
end;}
function fc(x: complex; c: complex; n: integer): complex;
begin
fc := complex_sum(x.power(n), c);
@ -63,9 +68,9 @@ end;
procedure setDefaultArgs(var args: TArgs);
begin
with args do begin
power := 2;
width := 512;
height := 512;
power := 2;
zoom := 1;
center_x := 0;
center_y := 0;
@ -157,30 +162,6 @@ var
out_path, fname: string;
px_data: TPxData;
begin
{img.init();
img.open('./images/k.bmp');
// draw sin
for i := 0 to img.get_width() - 1 do begin
color.set_color(255, 0, 0);
img.pixel_data[i][f(i)] := color;
end;
// convert color
for i := 0 to img.get_width() - 1 do begin
for j := 0 to img.get_height() - 1 do begin
color := img.pixel_data[i][j];
new_color.r := color.b;
new_color.g := color.g;
new_color.b := color.r;
img.pixel_data[i][j] := new_color;
end;
end;
img.set_width(400);
img.set_height(400);
img.save('./images/generated/k_generic.bmp', false);
img.done();}
setDefaultArgs(args);
if (getArgs(args)) then begin
@ -195,19 +176,6 @@ begin
img.done();
writeln(fname);
{color.set_color(255, 255, 255);
img.init(100, 100, color);
color.set_color(0, 255, 0);
for i := 0 to img.get_width() - 1 do begin
for j := 0 to img.get_height() - 1 do begin
if (check_a(i, j)) then begin
img.pixel_data[i][j] := color;
end;
end;
end;
img.save('./images/generated/circle.bmp', false);
img.done();}
end else begin
writeln(help_text);
end;

View File

@ -12,8 +12,6 @@ type
procedure update(px: extended; py: extended);
end;
function get_filename(base_name: string; zoom: extended; center_x: extended; center_y: extended): string;
implementation
procedure Point2D.update(px: extended; py: extended);
@ -22,16 +20,5 @@ begin
y := py;
end;
function get_filename(base_name: string; zoom: extended; center_x: extended; center_y: extended): string;
var
z, cx, cy: string;
begin
z := FloatToStr(zoom);
cx := FloatToStr(center_x);
cy := FloatToStr(center_y);
get_filename := base_name + '_(z=' + z + ';cx=' + cx + ';cy=' + cy + ').bmp'
end;
begin
end.