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
be an existing image given : var image1:TImage; there is a class TMapwin, defined below, which does it all. var mw1,mw2:TMapWin; // define two graphs mw1:=TMapWin.create(image1); // create in the image1 context mw1.left:=0; mw1.width:=image1.width; // use the whole width of the image mw1.top:=0; mw1.height:=image1.height; // use the full height of the image mw1.xlow:=0; mw1.xhigh:=2*pi; // define the world [0..2pi,-1.1..1.1] mw1.ylow:=-1.1; mw1.yhigh:=1.1; for i:=0 to image1.width-1 do begin // scan along X x:=mw1.getx(i); // get the float of X y:=sin(x); // calc the function mw1.putpixel(x,y,clBlack); // display the point end; and now a second graph : mw2:=TMapWin.create(image1); // create in the image1 context mw2.left:=0; mw2.width:=image1.width; // again the full image mw2.top:=0; mw2.height:=image1.height; mw2.xlow:=1e-6; mw2.xhigh:=1; // a different world mw2.ylow:=-14; mw2.yhigh:=0; mw2.xlog:=true; // logarithmic in X for i:=0 to image1.width-1 do begin // as above ... x:=mw2.getx(i); y:=ln(x); mw2.putpixel(x,y,clred); end; a cursor : // cursor predefined as cross on the image, label : mouselabel exists procedure TForm1.ImageMouseMove(x,y:integer...); var sx,sy:float; begin mw1.screentofloat(x,y,sx,sy); mouselabel.caption:=format('%8.5g %8.5g',[sx,sy]); end;
type float=extended; TMapWin = class(TObject) private { Private declarations } fimage:TImage; ftlx,ftly,fbrx,fbry,fwidth,fheight:integer; fxlow,fxhigh,fylow,fyhigh,fdx,fdy:float; fdrawclip,fxlog,fylog,fprotectlog:boolean; protected { Protected declarations } procedure setimage(i:TImage); procedure setTLX(u:integer); procedure setTLY(u:integer); procedure setWidth(u:integer); procedure setHeight(u:integer); procedure setxlow(z:float); procedure setxhigh(z:float); procedure setylow(z:float); procedure setyhigh(z:float); procedure setxlog(b:boolean); procedure setylog(b:boolean); function mapW2SxLin(xf:float):integer; function mapW2SyLin(yf:float):integer; function mapW2SxLog(xf:float):integer; function mapW2SyLog(yf:float):integer; function mapS2WxLin(xs:integer):float; function mapS2WyLin(ys:integer):float; function mapS2WxLog(xs:integer):float; function mapS2WyLog(ys:integer):float; public { Public declarations } constructor create(image:TImage); // must exist or NIL destructor destroy; override; procedure FloatToScreen(xf,yf:float;var xs,ys:integer); virtual; procedure ScreenToFloat(xs,ys:integer;var xf,yf:float); virtual; procedure clear; procedure putpixel(x,y:float;color:TColor); virtual; procedure putline(x1,y1,x2,y2:float;color:TColor); virtual; // not yet procedure VLine(x:float;color:TColor); virtual; // vertical line procedure HLine(y:float;color:TColor); virtual; // horizontal line function getX(i:integer):float; // i:=0..width-1 function getY(i:integer):float; // i:=0..height-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 xlow:float read fxlow write setXLow; property ylow:float read fylow write setYLow; property xhigh:float read fxhigh write setXHigh; property yhigh:float read fyhigh write setYHigh; property dx:float read fdx; property dy:float read fdy; property drawclipped:boolean read fdrawclip write fdrawclip; property xlog:boolean read fxlog write setxlog; property ylog:boolean read fylog write setylog; property protectlog:boolean read fprotectlog write fprotectlog; end; procedure Register; implementation uses math; type TMyPlotException=Class(Exception); //........................................................................... procedure TMapWin.setimage(i:TImage); begin fimage:=i; end; procedure TMapWin.setTLX(u:integer); begin ftlx:=u; end; procedure TMapWin.setTLY(u:integer); begin ftly:=u; end; procedure TMapWin.setWidth(u:integer); begin fbrx:=ftlx+u; fwidth:=u; end; procedure TMapWin.setHeight(u:integer); begin fbry:=ftly+u; fheight:=u; end; procedure TMapWin.setxlow(z:float); begin fxlow:=z; end; procedure TMapWin.setxhigh(z:float); begin fxhigh:=z; end; procedure TMapWin.setylow(z:float); begin fylow:=z; end; procedure TMapWin.setyhigh(z:float); begin fyhigh:=z; end; procedure TMapWin.setxlog(b:boolean); begin fxlog:=b; if b then begin // set log if xlow=0 then xlow:=1e-24; end; end; procedure TMapWin.setylog(b:boolean); begin fylog:=b; if b then begin // set log if ylow=0 then ylow:=1e-24; end; end; function TMapWin.mapW2SxLin(xf:extended):integer; begin result:=round(ftlx+(xf-fxlow)*(width)/(fxhigh-fxlow)); end; function TMapWin.mapW2SyLin(yf:extended):integer; begin result:=round(fbry-(yf-fylow)*(height)/(fyhigh-fylow)); end; function TMapWin.mapW2SxLog(xf:extended):integer; begin result:=round(ftlx+(ln(xf/fxlow)/ln(fxhigh/fxlow))*(width)); end; function TMapWin.mapW2SyLog(yf:extended):integer; begin result:=fbry-round((ln(yf/fylow)/ln(fyhigh/fylow))*(height)); end; function TMapWin.mapS2WxLin(xs:integer):extended; begin result:=fxlow+(xs-ftlx)*(fxhigh-fxlow)/(width); end; function TMapWin.mapS2WyLin(ys:integer):extended; begin result:=fyhigh-(ys-ftly)*(fyhigh-fylow)/(height); end; function TMapWin.mapS2WxLog(xs:integer):extended; begin result:=fxlow*exp(((xs-ftlx)/(width))*ln(fxhigh/fxlow)); end; function TMapWin.mapS2WyLog(ys:integer):extended; begin result:=fyhigh/exp(((ys-ftly)/(height)*ln(fyhigh/fylow))); end; constructor TMapWin.create(image:TImage); begin inherited create; fimage:=image; fdrawclip:=true; fprotectlog:=true; xlow:=0; ylow:=0; xhigh:=1; yhigh:=1; xlog:=false; ylog:=false; ftlx:=0;ftly:=0; if image<>nil then begin width:=image.width; height:=image.height; end else begin width:=100; height:=100; end; end; destructor TMapWin.destroy; begin inherited destroy; end; procedure TMapWin.FloatToScreen(xf,yf:float;var xs,ys:integer); begin if ((fxlog)and(xf<0))or((fylog)and(yf<0)) then raise(TMyPlotException.create('TMapWin: Number for log axis smaller than zero')); if fxlog then xs:=mapW2SxLog(xf) else xs:=mapW2SxLin(xf); if fylog then ys:=mapW2SyLog(yf) else ys:=mapW2SyLin(yf); end; procedure TMapWin.ScreenToFloat(xs,ys:integer;var xf,yf:float); begin if fxlog then xf:=mapS2WxLog(xs) else xf:=mapS2WxLin(xs); if fylog then yf:=mapS2WyLog(ys) else yf:=mapS2WyLin(ys); end; procedure TMapWin.clear; begin if assigned(fimage) then begin fimage.canvas.Pen.color:=clWhite; fimage.canvas.brush.color:=clWhite; fimage.canvas.rectangle(ftlx,ftly,fbrx,fbry); end; end; procedure TMapWin.putpixel(x,y:float;color:TColor); var ix,iy:integer; var cx,cy:boolean; begin if ((fxlog)and(x < 0))or((fylog)and(y < 0)) then begin if fprotectlog then exit else raise(TMyPlotException.create('Number for log axis smaller than zero')); end; cx:=false; cy:=false; ix:=0; iy:=0; if (x < fxlow) then begin ix:=ftlx; cx:=true; end; if (x > fxhigh) then begin ix:=fbrx-1; cx:=true; end; if (y < fylow) then begin iy:=fbry-1; cy:=true; end; if (y > fyhigh) then begin iy:=ftly; cy:=true; end; if not cx then begin if fxlog then ix:=mapW2SxLog(x) else ix:=mapW2SxLin(x); end; if (not cy) then begin if fylog then iy:=mapW2SyLog(y) else iy:=mapW2SyLin(y); end; if (cx or cy)and(not fdrawclip) then exit; if assigned(fimage) then fimage.canvas.pixels[ix,iy]:=color; end; procedure TMapWin.putline(x1,y1,x2,y2:float;color:TColor); var cx1,cx2,cy1,cy2:integer; begin end; procedure TMapWin.VLine(x:float;color:TColor); // vertical line var ix,iy:integer; cx:boolean; begin if ((fxlog)and(x < 0))then begin if fprotectlog then exit else raise(TMyPlotException.create('Number for log axis smaller than zero')); end; cx:=false; ix:=0; iy:=0; if (x < fxlow) then begin ix:=ftlx; cx:=true; end; if (x > fxhigh) then begin ix:=fbrx-1; cx:=true; end; if not cx then begin if fxlog then ix:=mapW2SxLog(x) else ix:=mapW2SxLin(x); end; if (cx)and(not fdrawclip) then exit; if assigned(fimage) then begin fimage.canvas.pen.color:=color; fimage.canvas.moveto(ix,ftly); fimage.canvas.lineto(ix,fbry); end; end; procedure TMapWin.HLine(y:float;color:TColor); // horizontal line var ix,iy:integer; cy:boolean; begin if ((fylog)and(y < 0))then begin if fprotectlog then exit else raise(TMyPlotException.create('Number for log axis smaller than zero')); end; cy:=false; ix:=0; iy:=0; if (y < fylow) then begin iy:=fbry; cy:=true; end; if (y > fyhigh) then begin iy:=ftly-1; cy:=true; end; if not cy then begin if fylog then iy:=mapW2SyLog(y) else iy:=mapW2SyLin(y); end; if (cy)and(not fdrawclip) then exit; if assigned(fimage) then begin fimage.canvas.pen.color:=color; fimage.canvas.moveto(ftlx,iy); fimage.canvas.lineto(fbrx,iy); end; end; function TMapWin.getX(i:integer):float; // i:=0..width-1 begin if fxlog then result:=mapS2WxLog(i) else result:=mapS2WxLin(i); end; function TMapWin.getY(i:integer):float; // i:=0..height-1 begin if fylog then result:=mapS2WyLog(i) else result:=mapS2WyLin(i); end;