{$N+}
Program Lab;
uses crt, Types, Transf, IOGeom, GrGeom, Graph, OPolig, Poligon, Punct;

(****************************************
 *  Acesta este un program demonstrativ
 *  de geometrie computationala.
 *  Se efectueaza operatii asupra poligonului
 *  simplu, stelat, convex
 *  si diferite calcule asupra lor.
 *
 *  Aria poligonului simplu
 *
 *  Algoritmi: direct, Graham, varianda Andrew, Greedy.
 *
 *
 * Puncte de intersectie:
 *  - Intersectia a doua segmente
 *  - Intersectia a unei drepte cu un segment
 *  - Intersectia a doua drepte
 *  - Intersectia unui set de segmente
 *    (segmentul care intersecteaza un nr. maxim de segmente)
 *
 * Transformarea coordonatelor:
 *  - Trecerea de la coordonate carteziene la cele polare
 *  - Deplasarea unui set de puncte
 *  - Rotatia unui set de puncte
 *
 *  Programul reprezinta grafic rezultatele
 *  calculelor.
 *
 *  Poate fi nevoie de DosBox
 *  pentru a lansa programul (Windows 7/Vista)
 *
 *
 *  Taste de control:
 *    <esc>                 - iesire
 *    <enter>               - citirea datelor de la tastatura
 *    'O'                   - salvarea datelor
 *    Up, Down, Left, Right - deplasari
 *    >, <                  - rotirea
 *    +, -                  - dimensiuni
 *    1, 2, 3, 0, F, B, S   - comutare moduri
 *
 ****************************************)

const
  filein    = 'Poligon.tin';
  fileout   = 'Lab.txt';
  fileinfas = 'Infas.txt';

  cPoligon = BLUE;
  cPuncte  = RED;
  cInfas   = YELLOW;
  cText    = WHITE;


var
  pg            : TPoligon;
  g, C          : TPunct;
  dir, mv       : TPunct;
  alfa, a       : TNumber;
  moved, pressed: boolean;

function Friction(v: TNumber): TNumber; begin Friction := Trunc(v * 0.8 * 100)/100; end;

begin
  clrscr;
  alfa := 0;
  { fit_big, fit_small, s_accel, s_polig, s_infas, s_rect }
  gr_set := [s_infas, s_rect, s_accel, fit_big, fit_small];
  mv := ZeroP;

  pg.Init(0);
  with pg do begin
    { Citirea datelor din fisierul <filein>, daca exista }
    LoadFromFile(filein);

    { Citirea coordonatelor punctelor de la tastatura }
    if nr = 0 then begin
       QueryInput(0);
       SaveToFile(filein);
    end;
    if IsSimplu and not SwitchGrSet(s_polig) then SwitchGrSet(s_polig);

    { Initierea modului grafic }
    InitGr(0);
    ChgPg; {Skimbam pagina vizibila cu cea activa}

    moved := true;
    repeat
      {Desenarea elementelor grafice}
      if moved or pressed then begin
        { Curatirea portului vizual }
        { ClearViewPort; Substituit de catre ChgPg }


        { Desenarea elementelor grafice }
        if GetGrSet(s_polig) then DrowPoligon(cPoligon);
                                  DrowPoints(cPuncte);
        if GetGrSet(s_infas) then DrowM(cInfas);

        { Hasurarea suprafetii poligonului }
        if GetGrSet(s_filrect) and (a = 0) and is_nil_vec(mv) and (not keypressed) then
          FillRect(cInfas, cPuncte);

        { Afisarea informatiei }
        SetColor(cText);
        drow_poz(g, alfa);
        if IsSimplu then OutTextXY(GetMaxX - 120, 0, 'Poligon simplu');
        moved := false;
        ChgPg; {Skimbam pagina vizibila cu cea activa}
      end;
      if GetGrSet(s_rect) then DrowRect(WHITE);

      { Asteptam un pic ca utilizatorul sa reuseasca sa vada imaginea desenata }
      delay(10);

      pressed := keypressed ;
      if GetGrSet(s_accel) or pressed then begin
        {Controlul tastelor}
        if pressed then begin
           case key_control(dir, a, 10, ReadKey) of
           #27: Break;  {Iesire din repeat}
           #13: QueryInput(0);
           'O': Output;
           end;
           sum_vec(mv, mv, dir);
        end;
        {Rotatii}
        if a <> 0 then begin
          RotateGrad(a, g);
          alfa := alfa + a;
          if alfa >  180 then alfa := alfa - 360 else
          if alfa < -180 then alfa := alfa + 360 ;
          a := Friction(a);
          moved := true;
        end;

        {Deplasari}
        if MoveRel(mv) <> 0 then with mv do begin
          Center(g);
          x := Friction(x);
          y := Friction(y);
          moved := true;
        end;

        {Daca nu este in modul de accelerare, vectorul de acceleratie se anuleaza}
        if not GetGrSet(s_accel) then begin
          a  := 0;
          mv := ZeroP;
        end;
      end;
    until false; {Ciclul de baza e o iteratie infinita, intrerupta de catre utilizator}

    { Inchidem modul grafic }
    CloseGr;

    { Salvarea rezultatului in fisiere }
    SaveToFile(fileout);
    SaveToFile(fileinfas);
  end;
  pg.Done; {Eliberam memoria ocupata de poligon}
  Halt(0); {Iesirea normala din program}
end.