| Scientific programming |
(Event-driven programming)
This is the enhancement of the project Cubic polynomial plot. The project uses an interface-based mathematical library PasMatLib.
This program displays the plot for a cubic polynomial: C0 + C1 x + C2 x2 + C3 x3.
Subjects covered:
Start Delphi. An empty form is created by default. Select File
Save
Project As, and in
Delphi Project directory create the directory SciProg as well as the subdirectory
CubicPolinomial. Save Unit1 as fPolynomial and Project1 as Polynomial2.
You can open and view Polynomial.dpr (program unit) and fPolynomial.pas (form unit). Delphi also generates several files with IDE settings and resources (see "Delphi generated files" in Delphi Help).
Follow all the steps from the previous project, but do not drop the PaintBox component on PanelPlot. Instead of this we will create the component TPlotBox2D dynamically.
Add to the uses section the following units
uMatTypes, // General types uDynArrays, // Dynamic interface-based arrays uDynArrUtils, // Dynamic arrays utilities uGraph2D; // 2D plot
Before type add
const n = 50;
Add to the private section of TForm1 the following code:
private
{ Private declarations }
c0, c1, c2, c3, Cmin, Cmax: TFloat;
Xmin, Xmax, Ymin, Ymax: TFloat;
PlotBox2D: TPlotBox2D;
xa, ya: IFArr1D;
dx: TFloat;
function p3(x: TFloat): TFloat;
procedure Plotting(Sender: TObject);
procedure SetParameters;
TFloat is set to double in the unit uMatTypes but can be reset to single or extended if necessary. TInt is set to integer (longint in earlier versions).
Select PanelPlot and set its BevelInner property to bvLowered. Press Ctrl-SHIFT-c and Delphi creates the empty functions in the implementation section. Add the reference to the Math unit right after the implementation.
Add the following code into the created functions.
// Cubic polynomial
function TForm1.p3(x: TFloat): TFloat;
begin
result := c0+x*(c1+x*(c2+x*c3));
end;
// Reads parameters from Edits and Scrollbars,
// Calculates arrays
procedure TForm1.SetParameters;
var
i: TInt;
x: TFloat;
begin
Xmin := StrToFloat(EditXmin.Text);
Xmax := StrToFloat(EditXmax.Text);
Cmin := StrToFloat(EditCmin.Text);
Cmax := StrToFloat(EditCmax.Text);
c0 := Cmin + (Cmax-Cmin)*ScrollBarC0.Position/ScrollBarC0.Max; // Min = 0
c1 := Cmin + (Cmax-Cmin)*ScrollBarC1.Position/ScrollBarC1.Max; // Min = 0
c2 := Cmin + (Cmax-Cmin)*ScrollBarC2.Position/ScrollBarC2.Max; // Min = 0
c3 := Cmin + (Cmax-Cmin)*ScrollBarC3.Position/ScrollBarC3.Max; // Min = 0
for i := xa.Lo1 to xa.Hi1 do
begin
xa[i] := x;
ya[i] := p3(x);
x := x + dx;
end;
end;
Form.OnCreate event handler
Select Form1 from the drop-down box in the Object Inspector and flip to the Events tab. Select OnCreate and double-click on the white field to the right. It creates the procedure FormCreate in the implementation section. Add the call to SetParameters:
procedure TForm1.FormCreate(Sender: TObject);
begin
xa := TFArr1D.Create(n); // Creation of arrays [1..n]
ya := TFArr1D.Create(n); // they will automatically destroyed
SetParameters;
// plot creation
PlotBox2D := TPlotBox2D.Create(self, PanelPlot); // PanelPlot is the parent of PlotBox2D
// self (Form1) is the owner and it will take care of the destruction of PlotBox2D
PlotBox2D.NXTicks := 5;
PlotBox2D.NYTicks := 5;
PlotBox2D.XTitle := 'x';
PlotBox2D.YTitle := 'F(x)';
PlotBox2D.OnPaint := Plotting; // event handler assignment
// Set to nil to disconnect the event handler
end;
Now PlotBox automatically rescale axes and transforms physical to screen coordinates. It makes the code much simpler.
procedure TForm1.Plotting(Sender: TObject);
var
i: TInt;
OldColor: TColor;
begin
MinMaxVec(ya, Ymin, Ymax); // for several functions use 2D array and MinMaxMat
if Ymax = Ymin then // just in case ...
Ymax := Ymax +0.1;
// incluse zero line in limits
Ymin := min(Ymin, 0);
Ymax := max(Ymax, 0);
PlotBox2D.SetLimits(Xmin, Xmax, Ymin, Ymax);
PlotBox2D.PlotFrame;
OldColor := PlotBox2D.PenColor;
PlotBox2D.PenColor := clBlue;
PlotBox2D.PenWidth := 2;
i := xa.Lo1;
PlotBox2D.MoveToF(xa[i],ya[i]);
for i := xa.Lo1+1 to xa.Hi1 do
begin
PlotBox2D.LineToF(xa[i],ya[i]);
end;
PlotBox2D.PenColor := clRed;
PlotBox2D.PenWidth := 1;
PlotBox2D.LineF(Xmin, 0, Xmax, 0);
PlotBox2D.PenColor := OldColor; // restore
end;
OnPaint occurs when the PaintBox receives a Windows paint message. It happens, for example, when the PaintBox is resized.
The last event handler processes the scrollbars' movement. Select e.g. ScrollBarC0 and its OnChange event. Create the ScrollBarC0Change procedure:
procedure TForm1.ScrollBarC0Change(Sender: TObject); begin SetParameters; Plotting(Sender); end;
Select the same procedure for the rest of the scrollbars.
Run the program:
The project code for Delphi 7 can be downloaded here.
The picture (plot) can be saved as a bitmap or JPEG file using the methods SaveToBMP and SaveToJPEG respectively.
The object TFormPlot can be used for plotting a function (see the project TestGraph2D in \PasMatLib\Tests\TestGraph2D).
(in preparation)
(in preparation)
| Scientific programming |
©Nikolai V. Shokhirev, 2004-2005