Advertisement
Egor_Vakar

(Delphi) lab 6.2 PaintUnit

Apr 27th, 2022
168
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 10.05 KB | None | 0 0
  1. unit PaintUnit;
  2.  
  3. interface
  4.  
  5. uses
  6.   Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  7.   Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls;
  8.  
  9. type
  10.   TPaintForm = class(TForm)
  11.     PaintBox: TPaintBox;
  12.     procedure FormKeyPress(Sender: TObject; var Key: Char);
  13.     procedure FormActivate(Sender: TObject);
  14.     procedure PaintBoxPaint(Sender: TObject);
  15.  
  16.   private
  17.     { Private declarations }
  18.   public
  19.     { Public declarations }
  20.   end;
  21.  
  22. var
  23.   PaintForm: TPaintForm;
  24.  
  25. implementation
  26.  
  27. {$R *.dfm}
  28.  
  29. uses
  30.     MainUnit;
  31. const
  32.     MAX = 10000;
  33. type
  34.     Arr = array[1..MAX] of Integer;
  35.     Matrix = array of array of Integer;
  36.     Res = array of Matrix;
  37.  
  38. procedure TPaintForm.FormActivate(Sender: TObject);
  39. var
  40.     Splits, Vertical, Horizontal, CellWidth, CellHeight, i, j, Counter: Integer;
  41. begin
  42.     PaintForm.Height := Screen.Height + 5;
  43.     PaintForm.Width := Screen.Width + 5;
  44.     PaintBox.Height := PaintForm.Height - 45;
  45.     PaintBox.Width := PaintForm.Width - 20;
  46.  
  47.     PaintBoxPaint(PaintBox);
  48. end;
  49.  
  50. procedure TPaintForm.FormKeyPress(Sender: TObject; var Key: Char);
  51. begin
  52.     if Key = #27 then
  53.         PaintForm.Close;
  54. end;
  55.  
  56. function FindSplit(a,b:arr; Number,kol:integer): Matrix;
  57. var
  58.     i, j, k, t:integer;
  59.     Matrx: Matrix;
  60. begin
  61.     SetLEngth(Matrx, Kol, Number);
  62.     for i := 0 to Kol - 1 do
  63.         for j := 0 to Number - 1 do
  64.             Matrx[i][j] := 0;
  65.     for k:=1 to Number-1 do
  66.         for i:=1 to Number-k do
  67.             if(b[i]>b[i+1]) then
  68.             begin
  69.                 t := b[i];
  70.                 b[i] := b[i+1];
  71.                 b[i+1] := t;
  72.                 t := a[i];
  73.                 a[i] :=a [i+1];
  74.                 a[i+1] := t;
  75.             end;
  76.     t := 1;
  77.     for i := 2 to Number do
  78.         if b[i]<>b[i-1] then
  79.             Inc(t);
  80.  
  81.     if(kol=t) then
  82.     begin
  83.         j := 0;
  84.         k := 0;
  85.         Matrx[j][k] := a[1];
  86.         for i := 2 to Number do
  87.             if b[i] <> b[i-1] then
  88.             begin
  89.                 SetLength(Matrx[j], k + 1);
  90.                 Inc(j);
  91.                 k := 0;
  92.                 Matrx[j][k] := a[i];
  93.             end
  94.             else
  95.             begin
  96.                 Inc(k);
  97.                 Matrx[j][k] := a[i];
  98.             end;
  99.         SetLength(Matrx[j], k + 1);
  100.         Result := Matrx;
  101.     end
  102.     else
  103.         Result :=  nil;
  104. end;
  105.  
  106. function FindAllSplits(Number, Kol: Integer): Res;
  107. var
  108.     a,
  109.     Prev, {номер предыдущего блока}
  110.     Next, {номер следующего блока: Next[I]=0, если блок I является последним блоком разбиения}
  111.     Blok:arr; {номер текущего блока}
  112.     j,i, {минимальный элемент текущего блока}
  113.     k, Counter, S:integer;
  114.     Forw:array[1..MAX] of boolean; {направление в котором движется элемент I, =true, если движется вперёд}
  115.     Answer: Res;
  116.     Temp: Matrix;
  117. begin
  118.   SetLength(Answer, MAX, Kol, Number);
  119.   for i := 0 to MAX - 1 do
  120.       Answer[i] := nil;
  121.   Counter := 0;
  122.  {инициализация исходного множества}
  123.  for i:=1 to Number do
  124.   begin
  125.    a[i]:=i;
  126.    Blok[i]:=1;
  127.    Forw[i]:=true;
  128.   end;
  129.   Next[1]:=0;
  130.   {Записать разбиение}
  131.   Temp := FindSplit(a,Blok,Number,kol);
  132.   if Temp <> nil then
  133.   begin
  134.       Answer[Counter] := Temp;
  135.       Inc(Counter);
  136.   end;
  137.   j:=Number; {j=активный элемент}
  138.   while j>1 do
  139.    begin
  140.     k:=Blok[j];
  141.     if Forw[j] then {j движется вперёд}
  142.      begin
  143.       if Next[k]=0 then {k есть последний блок}
  144.        begin
  145.         Next[k]:=j;
  146.         Prev[j]:=k;
  147.         Next[j]:=0;
  148.        end;
  149.       if Next[k]>j then {j образует новый блок}
  150.        begin
  151.          Prev[j]:=k;
  152.          Next[j]:=Next[k];
  153.          Prev[Next[j]]:=j;
  154.          Next[k]:=j;
  155.        end;
  156.       Blok[j]:=Next[k];
  157.      end
  158.     else {j движется назад}
  159.      begin
  160.       Blok[j]:=Prev[k];
  161.       if k=j then {j образует одноэлементный блок}
  162.        if Next[k]=0 then
  163.          Next[Prev[k]]:=0
  164.        else
  165.         begin
  166.          Next[Prev[k]]:=Next[k];
  167.          Prev[Next[k]]:=Prev[k];
  168.         end
  169.      end;
  170.     {Записать разбиение}
  171.     Temp := FindSplit(a,Blok,Number,kol);
  172.     if Temp <> nil then
  173.     begin
  174.         Answer[Counter] := Temp;
  175.         Inc(Counter);
  176.     end;
  177.     j:=Number;
  178.     while (j>1) and ((Forw[j] and (Blok[j]=j)) or (not Forw[j] and (Blok[j]=1)) ) do
  179.       begin
  180.         Forw[j]:=not Forw[j];
  181.         j:=j-1;
  182.       end;
  183.    end;
  184.    i := 0;
  185.    while Answer[i] <> nil do
  186.        Inc(i);
  187.    Setlength(Answer, i);
  188.    Result := Answer;
  189. end;
  190.  
  191. procedure TPaintForm.PaintBoxPaint(Sender: TObject);
  192. var
  193.     Number, Splits, Vertical, Horizontal, CellWidth, CellHeight, i, j, k, l, Counter, Line, XSpace, YSpace, TopCells, LeftCells, Radius: Integer;
  194.     AllSplits: Res;
  195. begin
  196.     PaintBox.Canvas.Pen.Width := 2;
  197.     PaintBox.Canvas.Brush.Color := clWhite;
  198.     PaintBox.Canvas.Rectangle(0,0,PaintBox.Width,PaintBox.Height);
  199.  
  200.     Number := MainForm.SpinEdit.Value;
  201.     Splits := StrToInt(MainForm.SplittingNumberLabel.Caption);
  202.     Horizontal := Trunc(sqrt(Splits));
  203.     if Splits <> 1 then
  204.         Inc(Horizontal);
  205.     if Horizontal * (Horizontal - 1) >= Splits  then
  206.         Vertical := Horizontal - 1
  207.     else
  208.         Vertical := Horizontal;
  209.     CellWidth := Round(PaintBox.Width / Horizontal);
  210.     CellHeight := Round(PaintBox.Height / Vertical);
  211.  
  212.     PaintBox.Canvas.Pen.Width := 0;
  213.     PaintBox.Canvas.Brush.Color := clBlack;
  214.     for i := 1 to Vertical - 1 do
  215.         PaintBox.Canvas.Rectangle(0,i * CellHeight - 1, PaintBox.Width,i * CellHeight + 1);
  216.     for i := 1 to Horizontal - 1 do
  217.         PaintBox.Canvas.Rectangle(i * CellWidth - 1,0,i * CellWidth + 1, PaintBox.Height);
  218.     Line := CellHeight div 3; //расстояние от центра ячейки до точки
  219.  
  220.     if Number < 7 then
  221.         PaintBox.Canvas.Pen.Width := 2
  222.     else
  223.         PaintBox.Canvas.Pen.Width := 1;
  224.     if Splits <> 1 then
  225.     begin
  226.         Counter := 2;
  227.         for i := Number - 1 downto 1 do
  228.         begin
  229.             AllSplits := FindAllSplits(Number, i);
  230.             for j := 0 to Length(AllSplits) - 1 do
  231.             begin
  232.                 if Counter mod Horizontal = 0 then
  233.                 begin
  234.                     LeftCells := Horizontal - 1;
  235.                     TopCells := Counter div Horizontal - 1;
  236.                 end
  237.                 else
  238.                 begin
  239.                     LeftCells := Counter mod Horizontal - 1;
  240.                     TopCells := Counter div Horizontal;
  241.                 end;
  242.                 for k := 0 to Length(AllSplits[j]) - 1 do
  243.                 begin
  244.                     if Length(AllSplits[j][k]) <> 1 then
  245.                     begin
  246.                         if Length(AllSplits[j][k]) = 2 then
  247.                         begin
  248.                             PaintBox.Canvas.MoveTo(CellWidth * LeftCells + CellWidth div 2 + Round(Line * sin(2* pi * AllSplits[j][k][0] / Number)), CellHeight * TopCells + CellHeight div 2 + Round(Line * cos(2* pi * AllSplits[j][k][0] / Number)));
  249.                             PaintBox.Canvas.LineTo(CellWidth * LeftCells + CellWidth div 2 + Round(Line * sin(2* pi * AllSplits[j][k][1] / Number)), CellHeight * TopCells + CellHeight div 2 + Round(Line * cos(2* pi * AllSplits[j][k][1] / Number)));
  250.                         end
  251.                         else
  252.                         begin
  253.                             PaintBox.Canvas.MoveTo(CellWidth * LeftCells + CellWidth div 2 + Round(Line * sin(2* pi * AllSplits[j][k][0] / Number)), CellHeight * TopCells + CellHeight div 2 + Round(Line * cos(2* pi * AllSplits[j][k][0] / Number)));
  254.                             for l := 1 to Length(AllSplits[j][k]) - 1 do
  255.                                 PaintBox.Canvas.LineTo(CellWidth * LeftCells + CellWidth div 2 + Round(Line * sin(2* pi * AllSplits[j][k][l] / Number)), CellHeight * TopCells + CellHeight div 2 + Round(Line * cos(2* pi * AllSplits[j][k][l] / Number)));
  256.                             PaintBox.Canvas.LineTo(CellWidth * LeftCells + CellWidth div 2 + Round(Line * sin(2* pi * AllSplits[j][k][0] / Number)), CellHeight * TopCells + CellHeight div 2 + Round(Line * cos(2* pi * AllSplits[j][k][0] / Number)));
  257.                         end;
  258.  
  259.                     end;
  260.                 end;
  261.                 Inc(Counter);
  262.             end;
  263.         end;
  264.     end;
  265.  
  266.  
  267.     PaintBox.Canvas.Brush.Color := clRed;
  268.     Counter := 0;
  269.     if Number = 1 then
  270.         Radius := 20
  271.     else
  272.         if Number < 7 then
  273.             Radius := 5
  274.         else
  275.             if Number < 10 then
  276.                 Radius := 2
  277.             else
  278.                 Radius := 1;
  279.     for i := 0 to Vertical - 1 do
  280.         for j :=  0 to Horizontal - 1 do
  281.             if Counter < Splits  then
  282.             begin
  283.                 if Number = 1 then
  284.                     PaintBox.Canvas.Ellipse(j * CellWidth + CellWidth div 2 - Radius, i * CellHeight + CellHeight div 2 - Radius, j * CellWidth + CellWidth div 2 + Radius, i * CellHeight + CellHeight div 2 + Radius)
  285.                 else
  286.                 begin
  287.                     PaintBox.Canvas.Ellipse(j * CellWidth + CellWidth div 2 - Radius, i * CellHeight + CellHeight div 2 - Radius + Line, j * CellWidth + CellWidth div 2 + Radius, i * CellHeight + CellHeight div 2 + Radius + Line);
  288.                 end;
  289.                 for k := 1 to Number - 1 do
  290.                 begin
  291.                     XSpace := Round(Line * sin(2* pi * k / Number));
  292.                     YSpace := Round(Line * cos(2* pi * k / Number));
  293.                     PaintBox.Canvas.Ellipse(j * CellWidth + CellWidth div 2 - Radius + XSpace, i * CellHeight + CellHeight div 2 - Radius + YSpace, j * CellWidth + CellWidth div 2 + Radius + XSpace, i * CellHeight + CellHeight div 2 + Radius + YSpace);
  294.                 end;
  295.  
  296.                 Inc(Counter);
  297.             end;
  298.  
  299. end;
  300.  
  301. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement