where : ibrtses delphi
plotting complex functions
disclaimer
the source code of this page may not appear correctly in certain browsers
due to special characters. Have a look at the source of this HTML page
with notepad instead
There are various ways to plot complex functions. This component was thought
to do them all, but till now, only amplitude(as log) and phase(as linear) against
a log horizontal are implemented.
A sample plot (frequency response of a parallel resonance):
the code
the code as it is plots the amplitude as log in the upper half image,
the phase as linear in the lower half of the image with a common log
frequency axis. It is composed of two float plots and requires
the complex unit
{ nonvisual component - does the mapping of coordinate system to screen
requires an image to plot on.
uses two float plot fields, one for the amplitude and one for the phase
advantage : multiple plots can be done onto one image
the image has to exist before assigning the image
use :
procedure TForm1.gobtnClick(Sender: TObject);
var
S,D,U:ComplexPtr;
x:integer;
begin
cpw:=TComplexMapWin.create(image1);
cpw.clear;
cpw.flow:=1e6;
cpw.fhigh:=3e7;
cpw.mina:=1e-1;
cpw.maxa:=1e4;
Ra:=new(ComplexPtr);
Ca:=new(ComplexPtr);
La:=new(ComplexPtr);
for x:=0 to image1.width-1 do begin // scan horizontally
xs:=cpw.getx(x); // get real x
Ca^.a:=0;
Ca^.b:=-1/(2*pi*xs*cav);
La^.a:=0;
La^.b:=2*pi*xs*lav;
Ra^.a:=rav;
Ra^.b:=0;
s:=C_ParallelN(La,Ca);
d:=C_ParallelN(S,Ra);
C_R2P(d);
cpw.putpixel(d^,xs,clblack); // display this value
dispose(S);
dispose(D);
end;
cpw.destroy;
cpw:=nil;
end;
}
unit ComplexPlotWin;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
extctrls,ComplexRec,PlotWin;
type
float=extended;
cwmodetype=(saAP,saRI); // real/imag or abs/phase
TComplexMapWin = class(TObject)
private
{ Private declarations }
fimage:TImage;
fmw1,fmw2:TMapWin;
ftlx,ftly,fbrx,fbry,fwidth,fheight:integer;
fflow,ffhigh,fmina,fmaxa:float;
fmode:cwmodetype;
protected
{ Protected declarations }
procedure setimage(i:TImage);
procedure setTLX(u:integer);
procedure setTLY(u:integer);
procedure setWidth(u:integer);
procedure setHeight(u:integer);
procedure setflow(f:float);
procedure setfhigh(f:float);
procedure setmina(a:float);
procedure setmaxa(a:float);
public
{ Public declarations }
constructor create(image:TImage); // must exist or NIL
destructor destroy; override;
procedure ComplexToScreen(z:Complex;f:float;var xs,ya,yp:integer); virtual;
procedure ScreenToFloat(xs,ys:integer;var xf,yf:float); virtual;
procedure clear;
procedure putpixel(z:Complex;f:float;color:TColor); virtual;
function getX(i:integer):float; // i:=0..width-1
published
{ Published declarations }
property image:TImage read fimage write setimage;
property left:integer read ftlx write setTLX; // with respect to image
property top:integer read ftly write setTLY; // with respect to image
property width:integer read fwidth write setWidth; // with respect to image
property height:integer read fheight write setHeight; // with respect to image
property mode:cwmodetype read fmode write fmode;
property flow:float read fflow write setflow; // frequency
property fhigh:float read ffhigh write setfhigh; // frequency
property mina:float read fmina write setmina; // absolute value
property maxa:float read fmaxa write setmaxa; // absolute value
end;
procedure Register;
implementation
uses math;
type TMyPlotException=Class(Exception);
//...........................................................................
procedure TComplexMapWin.setimage(i:TImage);
begin
fimage:=i;
fmw1.image:=i;
fmw2.image:=i;
end;
procedure TComplexMapWin.setTLX(u:integer);
begin ftlx:=u; end;
procedure TComplexMapWin.setTLY(u:integer);
begin ftly:=u; end;
procedure TComplexMapWin.setWidth(u:integer);
begin fbrx:=ftlx+u; fwidth:=u; end;
procedure TComplexMapWin.setHeight(u:integer);
begin fbry:=ftly+u; fheight:=u; end;
procedure TComplexMapWin.setflow(f:float);
begin
fflow:=f;
fmw1.xlow:=f;
fmw2.xlow:=f;
end;
procedure TComplexMapWin.setfhigh(f:float);
begin
ffhigh:=f;
fmw1.xhigh:=f;
fmw2.xhigh:=f;
end;
procedure TComplexMapWin.setmina(a:float);
begin
fmina:=a;
fmw1.ylow:=a;
end;
procedure TComplexMapWin.setmaxa(a:float);
begin
fmaxa:=a;
fmw1.yhigh:=a;
end;
constructor TComplexMapWin.create(image:TImage);
begin
inherited create;
fimage:=image;
fmode:=saAP;
fmw1:=TMapwin.create(image);
fmw2:=TMapWin.create(image);
if fmode=saAP then begin
flow:=0.1; fhigh:=100;
fmina:=1e-9; fmaxa:=1;
fmw1.xlow:=flow; fmw2.xlow:=flow;
fmw1.xhigh:=fhigh; fmw2.xhigh:=fhigh;
fmw1.YLow:=fmina; fmw2.YLow:=-pi;
fmw1.YHigh:=fmaxa; fmw2.YHigh:=pi;
fmw1.xlog:=true; fmw2.xlog:=true;
fmw1.ylog:=true; fmw2.ylog:=false;
fmw1.protectlog:=true;
fmw1.top:=0; fmw2.top:=image.height div 2;
fmw1.height:=
image.height div 2-1; fmw2.height:=fmw1.height;
fmw1.left:=0; fmw2.left:=0;
fmw1.width:=image.width; fmw2.width:=image.width;
end
else begin//fmode=saRI
end;
end;
destructor TComplexMapWin.destroy;
begin
fmw1.destroy;
fmw2.destroy;
inherited destroy;
end;
procedure TComplexMapWin.ComplexToScreen(z:Complex;f:float;var xs,ya,yp:integer);
var ax,ay,bx,by:integer;
begin
if fmode=saAP then begin // z:=a,p
fmw1.floattoscreen(f,z.a,ax,ay);
fmw2.floattoscreen(f,z.b,bx,by);
xs:=ax; ya:=ay; yp:=by;
end;
end;
procedure TComplexMapWin.ScreenToFloat(xs,ys:integer;var xf,yf:float);
begin
if fmode=saAP then begin
if (ys>=fheight div 2) then // in the phase part
fmw2.ScreenToFloat(xs,ys-(fheight div 2),xf,yf)
else // absolute part
fmw1.ScreenToFloat(xs,ys,xf,yf);
end;
end;
procedure TComplexMapWin.clear;
begin
if assigned(fimage) then begin
fimage.canvas.Pen.color:=clWhite;
fimage.canvas.brush.color:=clWhite;
fimage.canvas.rectangle(ftlx,ftly,fbrx,fbry);
fimage.canvas.Pen.color:=clblack;
fimage.canvas.moveto(0,fimage.height div 2);
fimage.canvas.lineto(fimage.width,fimage.height div 2);
fimage.canvas.Pen.color:=clWhite;
end;
end;
procedure TComplexMapWin.putpixel(z:Complex;f:float;color:TColor);
begin
fmw1.putpixel(f,z.a,color);
fmw2.putpixel(f,z.b,color);
end;
function TComplexMapWin.getX(i:integer):float; // i:=0..width-1
begin
result:=fmw1.getx(i);
end;
procedure Register;
begin
// RegisterComponents('Samples', [TComplexMapWin]);
end;
end.
notes
This component is not yet complete, it just served the purpose
it was designed for.
I'll update it at a later date.
Feedback is welcome
sponsored links
Delphi
home
last updated: 26.jan.00
Copyright (99,2000) Ing.Büro R.Tschaggelar