Kreslení grafů

Následující text vznikl jen jako pomůcka pro výklad, náplní cvičení je namalovat graf funkce. Pokud rozumíte komentářům (jsou psány úmyslně anglicky, aby byly univerzální), můžete si tvorbu grafu v osmi krocích vyzkoušet.

Tento program byl vytvořen na formuláři podle následujícího obrázku; také můžete dělat změny postupně do jediného tlačítka. V tom případě byste potřebovali formulář jen s jedním tlačítkem, jedním objektem typu TImage (obrázek, lišta Additional), a pokud chcete zadávat font nadpisu, pak FontDialog z lišty Dialogs:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    Image1: TImage;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    Button5: TButton;
    Button6: TButton;
    Button7: TButton;
    Button8: TButton;
    FontDialog1: TFontDialog;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure Button5Click(Sender: TObject);
    procedure Button6Click(Sender: TObject);
    procedure Button7Click(Sender: TObject);
    procedure Button8Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

{comment: the eight steps to draw a sine function}
procedure TForm1.Button1Click(Sender: TObject);
var
   i : integer;
 begin
   for i:=0 to 360 do
     image1.canvas.lineto(i+10,100 - round (50*sin(i) ));
 end;

{the line is strange, because Pascal calculates with radians;
   there are one line more, because before drawing a function
     we need to move the drawing cursor first}

procedure TForm1.Button2Click(Sender: TObject);
 var
   i : integer;
 begin
   image1.canvas.MOVEto(0+10,100 - round (50*sin(0) ));
   for i:=0 to 360 do
     image1.canvas.lineto(i+10,100 - round (50*sin(i/180*pi) ));
 end;

{sinus, but with wrong size - we need to convert to size of our image (in "h" variable)}

 procedure TForm1.Button3Click(Sender: TObject);
 var
   i,h : integer;
 begin
   h := image1.height;
   image1.canvas.moveto(0+10,h div 2 - round (h/2*sin(0/180*pi) ));
   for i:=0 to 360 do
     image1.canvas.lineto(i+10,h div 2 - round (h/2*sin(i/180*pi) ));
 end;

{colored function would be nice, and thick line looks better}

procedure TForm1.Button4Click(Sender: TObject);
 var
   i,h : integer;
 begin
   h := image1.height;
   image1.canvas.pen.color := clred;
   image1.canvas.pen.width := 3;
   image1.canvas.moveto(0+10,h div 2 - round (h*0.4*sin(0/180*pi) ));
   for i:=0 to 360 do
     image1.canvas.lineto(i+10,h div 2 - round (h*0.4*sin(i/180*pi) ));
 end;

{graph should be resamopled to all the width of the picture}

procedure TForm1.Button5Click(Sender: TObject);
 var
   i,h,w : integer;
 begin
   h := image1.height;
   w := image1.width;
   image1.canvas.pen.color := clred;
   image1.canvas.pen.width := 3;
   image1.canvas.moveto(0+10,h div 2 - round (h*0.4*sin(0/180*pi) ));
   for i:=0 to 360 do
     image1.canvas.lineto(round(i/360*(w-20))+10,h div 2 - round (h*0.4*sin(i/180*pi) ));
 end;

{we are still missing axis... important is to set back the pen width and color}

procedure TForm1.Button6Click(Sender: TObject);
 var
   i,h,w : integer;
 begin
   h := image1.height;
   w := image1.width;
   image1.canvas.pen.color := clred;
   image1.canvas.pen.width := 3;
   image1.canvas.moveto(0+10,h div 2 - round (h*0.4*sin(0/180*pi) ));
   for i:=0 to 360 do
     image1.canvas.lineto(round(i/360*(w-20))+10,h div 2 - round (h*0.4*sin(i/180*pi) ));
   image1.canvas.pen.color := clBlack;
   image1.canvas.pen.width := 1;
   image1.canvas.moveto(0+10, h div 2);
   image1.canvas.lineto(w-10, h div 2);
   image1.canvas.moveto(0+10, h div 2 - round (h*0.45*1 ));
   image1.canvas.lineto(0+10, h div 2 + round (h*0.45*1 ));
 end;

{some marks on horizontal axis (vertical would be the same) }

procedure TForm1.Button7Click(Sender: TObject);
 var
   i,h,w : integer;
 begin
   h := image1.height;
   w := image1.width;
   image1.canvas.pen.color := clred;
   image1.canvas.pen.width := 3;
   image1.canvas.moveto(0+10,h div 2 - round (h*0.4*sin(0/180*pi) ));
   for i:=0 to 360 do
     image1.canvas.lineto(round(i/360*(w-20))+10,h div 2 - round (h*0.4*sin(i/180*pi) ));
   image1.canvas.pen.color := clBlack;
   image1.canvas.pen.width := 1;
   image1.canvas.moveto(0+10, h div 2);
   image1.canvas.lineto(w-10, h div 2);
   image1.canvas.moveto(0+10, h div 2 - round (h*0.45*1 ));
   image1.canvas.lineto(0+10, h div 2 + round (h*0.45*1 ));

   for i:= 1 to 36 do
     begin
       image1.canvas.moveto(round(i/36*(w-20))+10,h div 2 - 3);
       image1.canvas.lineto(round(i/36*(w-20))+10,h div 2 + 3);
     end;
 end;

{the last step is the axis labeling}

procedure TForm1.Button8Click(Sender: TObject);
 var
   i,h,w : integer;
 begin
   h := image1.height;
   w := image1.width;
   image1.canvas.pen.color := clred;
   image1.canvas.pen.width := 3;
   image1.canvas.moveto(0+10,h div 2 - round (h*0.4*sin(0/180*pi) ));
   for i:=0 to 360 do
     image1.canvas.lineto(round(i/360*(w-20))+10,h div 2 - round (h*0.4*sin(i/180*pi) ));
   image1.canvas.pen.color := clBlack;
   image1.canvas.pen.width := 1;
   image1.canvas.moveto(0+10, h div 2);
   image1.canvas.lineto(w-10, h div 2);
   image1.canvas.moveto(0+10, h div 2 - round (h*0.45*1 ));
   image1.canvas.lineto(0+10, h div 2 + round (h*0.45*1 ));

   for i:= 1 to 36 do
     begin
       image1.canvas.moveto(round(i/36*(w-20))+10,h div 2 - 3);
       image1.canvas.lineto(round(i/36*(w-20))+10,h div 2 + 3);
     end;

   for i:= 0 to 17 do     {note: we can label the zero, but there are no place to write "360"}
      image1.canvas.textout(round(i/18*(w-20))+10+2,h div 2 - 3 +4,IntToStr(i*20));
   {caption of the graph}
   if fontdialog1.execute then image1.canvas.font:=fontdialog1.font;
   image1.canvas.textout(w div 2, 3, 'y=sin(x)');

 end;

end.

Výsledný vzhled programu je zde:

Je patrné, že nejlépe by bylo nechat graf vykreslit až po osách a jejich popisu, protože část číslice "180" překrývá čáru.

Poznámky.
Plochu je možné smazat (například v případě překreslování grafu) takto:

image1.canvas.filledrectangle...

Příklady:

  1. Popište i osu y.
  2. Nakreslete graf jiné funkce, např. tgh(x), v rozumném rozsahu.

Vykreslení dat z matice a

...