Program Fv_Rajzolas;
{ -------------------------------------------------------------------------
    Függvényrajzolás (Informatikai rendszerek tárgyhoz).

    Teljesebb, B-változat.

    Megoldás.
 -------------------------------------------------------------------------- }
{$IFNDEF FPC -- nem FreePascal=TurboPascal}
  {$f+ azért kell, hogy függvényt paraméterként adhassak át }
{$ENDIF}
  Uses
    {$IFNDEF FPC -- nem FreePascal=TurboPascal}
    Newdelay,
    {$ENDIF}
    Crt,Graph;
  Const
    MaxN 1024;                     {Maximum ennyi pontból állhat a függvény}
    Hol_a_BGI='';            {a BGI-driver a program mellett; FP-nek nem kell}
{ ------------------- A kirajzolandó függvények megadása: ------------------ }
  Type
    TEgyValtozosFv Record
                       tol,ig:Real;          {A fv. értelmezési tartománya}
                       fv:Function(x:Real):Real{A fv.-t kiszámoló FUNC.}
                       min,max:Real          {A fv. értékkészlete}
                     End;
  Function Sinx(x:Real):Real;
  Begin
    Sinx:=Sin(x);
  End;
  Function Cosx(x:Real):Real;
  Begin
    Cosx:=Cos(x);
  End;
  Function Gyokx(x:Real):Real;
  Begin
    Gyokx:=Sqrt(x);
  End;
  Function Kons3(x:Real):Real;
  Begin
    Kons3:=3;
  End;
  Const
  {$IFDEF FPC -- FreePascal}
    sinFv TEgyValtozosFv=(tol:-piig:pi;  fv:@Sinx;  min:-1.0max:1.0);
    CosFv TEgyValtozosFv=(tol:-piig:pi;  fv:@Cosx;  min:-1.0max:1.0);
    GyokFvTEgyValtozosFv=(tol:0;   ig:100fv:@Gyokxmin:0.0;  max:10.0);
    KonsFvTEgyValtozosFv=(tol:-75ig:75;  fv:@Kons3min:-1;   max:10);
  {$ELSE -- TurboPascal}
    sinFv TEgyValtozosFv=(tol:-piig:pi;  fv:Sinx;  min:-1.0max:1.0);
    CosFv TEgyValtozosFv=(tol:-piig:pi;  fv:Cosx;  min:-1.0max:1.0);
    GyokFvTEgyValtozosFv=(tol:0;   ig:100fv:Gyokxmin:0.0;  max:10.0);
    KonsFvTEgyValtozosFv=(tol:-75ig:75;  fv:Kons3min:-1;   max:10);
  {$ENDIF}
{ ---------------- A függvényértékeket tartalmazó vektorok: ---------------- }
  Type
    TKoordinatak   Array [1..MaxNof Real;
    TFuggvenyTabla Record
                       n  :Integer;
                       x,y:TKoordinatak;
                       minY,maxY:Real;
                     End;
  Var
    ftTFuggvenyTabla;
{ -------------------------- A megjelenítô ablakok: ------------------------ }
  Type
    TAblak Record
               bf,jaRecord x,y:IntegerEnd;
               cimkeString;
               szin Integer;
             End;
  Var
    aArray [1..4of TAblak;
    szel,
    magInteger{Aktuális szélességük és magasságuk}
    XMax,YMax,
    XMin,YMinInteger{ A teljes grafikus képernyô helye}
{ ------------------------ Egyéb globális változók: ------------------------ }
    cChar;

  Procedure Inic(Const cim:String);
    Var gd,gm,
        Integer;
  Begin
    {$IFDEF FPC -- FreePascal;
                   hogy a lássuk a vezérlő ablakban is a haladást:}
    ClrScr;
    Writeln(cim:40+(Length(cimDiv 2));
    {$ENDIF}
    gd:=Detect;
    InitGraph(gd,gm,Hol_a_BGI);
    SetBkColor(Black);
    ClearDevice;
    XMax:=GetMaxXYMax:=GetMaxY;
    XMin:=0YMin:=0;
    SetColor(White);
    Rectangle(XMin,YMinXMax,YMax);
    szel:=((XMax-XMinDiv 2)-4mag:=((YMax-YMinDiv 2)-TextHeight(' ');
    SetTextJustify(CenterText,TopText);
    OutTextXY(szel+1,2,cim);
    With a[1do
    Begin
      bf.x:=4bf.y:=4+TextHeight(' ');
      ja.x:=szelja.y:=bf.y+mag-4cimke:='1.ábra'szin:=Yellow
    End;
    With a[2do
    Begin
      bf.x:=XMax-szelbf.y:=4+TextHeight(' ');
      ja.x:=XMax-4ja.y:=bf.y+mag-4cimke:='2.ábra'szin:=Green
    End;
    With a[3do
    Begin
      bf.x:=4bf.y:=a[1].ja.y+8;
      ja.x:=szelja.y:=bf.y+mag-4cimke:='3.ábra'szin:=LightCyan
    End;
    With a[4do
    Begin
      bf.x:=XMax-szelbf.y:=a[2].ja.y+8;
      ja.x:=XMax-4ja.y:=bf.y+mag-4cimke:='Fejlesztési lehetöség'szin:=Brown
    End;
    For i:=to do
    Begin
      With a[ido
      Begin
        SetColor(szin);
        SetViewPort(bf.x,bf.yja.x,ja.y,ClipOn);
        Rectangle(0,0szel-4,mag-4);
        OutTextXY(szel Div 2,1,cimke);
      End;
    End;
  End;

  Procedure Feltolt(f:TEgyValtozosFvlep:RealVar ft:TFuggvenyTabla);
     Var xReal;
         iInteger;
  Begin
    x:=f.toli:=1;
    While x<=f.ig do
    Begin
      ft.x[i]:=xft.y[i]:=f.fv(x);
      x:=x+lepInc(i);
    End;
    ft.n:=i-1;                             {Ennyi pontból áll a függvénytábla}
    ft.minY:=f.minft.maxY:=f.max
  End;

  Procedure KoordinataTengelyek(ox,oy,xh,yh:Integer);
    Var cInteger;
  Begin
    c:=GetColorSetColor(White);
    Line(0,oyxh,oy); Line(ox,0ox,yh);
    SetColor(c);
  End;

  Procedure KirajzolP(a:TAblakt:TFuggvenyTabla); {Pontokbol rajzol}
    Var iInteger;
        Nx,NyReal;
        o0,s0szel,magInteger;

    Procedure PontRajzolas(x,y:Real);
      Var
        o,s:Integer;
    Begin
      o:=Trunc(Nx*x+o0); s:=s0-Trunc(Ny*y);
      PutPixel(o,s,a.szin);
    End;

  Begin {KirajzolP}
    {$IFDEF FPC -- FreePascal;
                   hogy a lássuk a vezérlő ablakban is a haladást:}
    Writeln('Rajzolás pontokkal');
    {$ENDIF}
    szel:=a.ja.x-a.bf.xmag:=a.ja.y-a.bf.y-TextHeight(' ')-1;
    SetViewPort(a.bf.x+2,a.bf.y+10a.ja.x-2,a.ja.y+1,ClipOn);
    SetColor(a.szin);
    Nx:=(szel-2-2+1)/(t.x[t.n]-t.x[1]); Ny:=mag/(t.maxY-t.minY);
    o0:=Trunc(-t.x[1]*Nx); s0:=Trunc(mag+t.minY*Ny);
    KoordinataTengelyek(o0,s0,
                        a.ja.x-a.bf.x-4,a.ja.y-a.bf.y-TextHeight(' ')-4);
    For i:=to t.do
    Begin
      PontRajzolas(t.x[i],t.y[i])
    End;
  End;{KirajzolP}

  Procedure KirajzolSz(aTAblaktTFuggvenyTabla); {Szakaszokbol rajzol}
    Var iInteger;
        Nx,NyReal;
        eo,es,
        o0,s0szel,magInteger;

    Procedure PontRajzolas(x,y:Real);
      Var
        o,s:Integer;
    Begin
      o:=Trunc(Nx*x+o0); s:=s0-Trunc(Ny*y);
      PutPixel(o,s,a.szin);
      eo:=oes:=s
    End;

    Procedure SzakaszRajzolas(x,y:Real);
      Var
        o,s:Integer;
    Begin
      o:=Trunc(Nx*t.x[i]+o0); s:=s0-Trunc(Ny*t.y[i]);
      Line(eo,es,o,s);
      eo:=oes:=s
    End;

  Begin {KirajzolSz}
    {$IFDEF FPC -- FreePascal;
                   hogy a lássuk a vezérlő ablakban is a haladást:}
    Writeln('Rajzolás szakaszokkal');
    {$ENDIF}
    szel:=a.ja.x-a.bf.xmag:=a.ja.y-a.bf.y-TextHeight(' ')-1;
    SetViewPort(a.bf.x+2,a.bf.y+10a.ja.x-2,a.ja.y+1,ClipOn);
    SetColor(a.szin);
    Nx:=(szel-2-2+1)/(t.x[t.n]-t.x[1]); Ny:=mag/(t.maxY-t.minY);
    o0:=Trunc(-t.x[1]*Nx); s0:=Trunc(mag+t.minY*Ny);
    KoordinataTengelyek(o0,s0,
                        a.ja.x-a.bf.x-4,a.ja.y-a.bf.y-TextHeight(' ')-4);
    PontRajzolas(t.x[1],t.y[1]);
    For i:=to t.do
    Begin
      SzakaszRajzolas(t.x[i],t.y[i])
    End;
  End;{KirajzolSz}

  Procedure KirajzolT(aTAblaktTFuggvenyTabla); {Teglakbol rajzol}
    Var iInteger;
        Nx,NyReal;
        Dxo0,s0szel,magInteger;

    Function Sgn(x:Real):Integer;
    Begin
      If x<then Sgn:=-else Sgn:=+1
    End;

    Procedure TeglaRajzolas(x,y:RealoszlopSzel:Integer);
      Var
        o,s:Integer;
    Begin
      o:=Trunc(Nx*x+o0); s:=s0-Trunc(Ny*y);
      Bar(o-oszlopSzel+1,s,o+oszlopSzel-1,s0-Sgn(y));
    End;

  Begin {KirajzolT}
    {$IFDEF FPC -- FreePascal;
                   hogy a lássuk a vezérlő ablakban is a haladást:}
    Writeln('Rajzolás téglalapokkal');
    {$ENDIF}
    szel:=a.ja.x-a.bf.xmag:=a.ja.y-a.bf.y-TextHeight(' ')-1;
    SetViewPort(a.bf.x+2,a.bf.y+10a.ja.x-2,a.ja.y+1,ClipOn);
    SetColor(a.szin); SetFillStyle(SolidFill,a.szin);
    Nx:=(szel-2-2+1)/(t.x[t.n]-t.x[1]); Ny:=mag/(t.maxY-t.minY);
    o0:=Trunc(-t.x[1]*Nx); s0:=Trunc(mag+t.minY*Ny);
    Dx:=Trunc(szel/t.n/2);
    KoordinataTengelyek(o0,s0,
                        a.ja.x-a.bf.x-4,a.ja.y-a.bf.y-TextHeight(' ')-4);
    For i:=to t.do
    Begin
      TeglaRajzolas(t.x[i],t.y[i],Dx)
    End;
  End;{KirajzolT}

Begin
  Inic('Sin fv');
  Feltolt(SinFv0.1ft);
  KirajzolP(a[1],ft);
  c:=ReadKey;
  KirajzolSz(a[2],ft);
  c:=ReadKey;
  KirajzolT(a[3],ft);
  c:=ReadKey;
  CloseGraph;

  Inic('Cos fv');
  Feltolt(CosFv0.1ft);
  KirajzolP(a[1],ft);
  c:=ReadKey;
  KirajzolSz(a[2],ft);
  c:=ReadKey;
  KirajzolT(a[3],ft);
  c:=ReadKey;
  CloseGraph;

  Inic('Négyzetgyök fv');
  Feltolt(GyokFv1ft);
  KirajzolP(a[1],ft);
  c:=ReadKey;
  KirajzolSz(a[2],ft);
  c:=ReadKey;
  KirajzolT(a[3],ft);
  c:=ReadKey;
  CloseGraph;

  Inic('Konstans fv');
  Feltolt(KonsFv1ft);
  KirajzolP(a[1],ft);
  c:=ReadKey;
  KirajzolSz(a[2],ft);
  c:=ReadKey;
  KirajzolT(a[3],ft);
  c:=ReadKey;
  CloseGraph;

End.