< -->

Program TrigonDemo;
{$G+,N+,E-,D-}
Uses Graph, CRT;
type
  Real = Extended;
const
  OldInt1Ch : Pointer = NIL;
  flag : Word = 0;
  Sx : Real = 20.0;
  Sy : Real = 20.0;
var
  D, R, e : Integer;
  x, y    : array [0..3] of Real;
  x_, y_  : array [0..3] of Integer;
  xp, yp  : array [0..3] of Integer;
  i  : Integer;
  yy : Real;
{Самые важные процедуры и функции - для определения положения точки}
{относительно треугольника}
{По двум точкам составлено уравнение прямой. Возвращает значение}
{функции в точке, положение которой относительно прямой нужно определить}
{=0, если точка лежит на прямой, <0 - выше, >0 - ниже}
Function FLine(indx1, indx2, dot : Integer) : Real;
begin
  FLine := (x[dot]-x[indx1])*(y[indx2]-y[indx1])-(y[dot]-y[indx1])*(x[indx2]-x[indx1]);
end;
Function WhereDot : Byte;
var
  tmp : Byte;
  t : Real;
  S : String;
begin
  if ((FLine(1, 2, 0)=0) and (FLine(3, 0, 1)*FLine(3, 0, 2)<=0)) or
     ((FLine(2, 3, 0)=0) and (FLine(1, 0, 2)*FLine(1, 0, 3)<=0)) or
     ((FLine(3, 1, 0)=0) and (FLine(2, 0, 3)*FLine(2, 0, 1)<=0)) then
  WhereDot := 0 else
  if (FLine(1, 2, 3)*FLine(1, 2, 0)>0) and (FLine(2, 3, 1)*FLine(2, 3, 0)>0) and (FLine(1, 3, 2)*FLine(1, 3, 0)>0)
  then WhereDot := 1 else WhereDot := 2;
end;
{Процедура ожидания обратного хода луча}
Procedure WaitRetrace;Assembler;
asm
             mov  dx, 03DAh
@VRTL1:
             in   al, dx
             test al, 8
             jnz  @VRTL1
@VRTL2:
             in al, dx
             test   al, 8
	     jnz     @VRTL2
             ret
end;
{++++++++++++++++++++++++++++++++++++++}
{Процедуры и функции для работы с мышью}
Procedure InitMouse; Assembler;
asm
    mov ax, 0
    int 33h
end;
Procedure ShowMouse; Assembler;
asm
    mov ax, 1
    int 33h
end;
Procedure HideMouse; Assembler;
asm
    mov ax, 2
    int 33h
end;
Function MouseButt : Word; Assembler;
asm
    mov ax, 3
    int 33h
    mov ax, bx
end;
Function MouseX : Word; Assembler;
asm
    mov ax, 3
    int 33h
    mov ax, cx
end;
Function MouseY : Word; Assembler;
asm
    mov ax, 3
    int 33h
    mov ax, dx
end;
Procedure MouseGotoXY(X, Y : Integer); Assembler;
asm
  mov   ax, 4
  mov   cx, word ptr X
  mov   dx, word ptr Y
  int   33h
end;
Function MouseIn(X1,Y1,X2,Y2: Integer): Boolean;
begin
  MouseIn := (MouseX>X1) and (MouseXY1) and (MouseY 0 do;
end;
{----------------------------------------}
{Установка счётчиков сигналов таймера}
Procedure SetInt1Ch; Assembler;
asm
 push   es

 mov    ax, 351Ch
 int    21h
 mov    word ptr OldInt1Ch, bx
 mov    word ptr OldInt1Ch+2, es
 mov    word ptr @OI1Ch, bx
 mov    word ptr @OI1Ch+2, es

 pop    es

 mov    ax, 251Ch

 push   ds

 mov    dx, seg @int1Ch
 mov    ds, dx
 mov    dx, offset @int1Ch
 int    21h

 pop    ds

 ret

@int1Ch:
 pushf
 push   ds
 push   ax

 mov    ax, seg flag
 mov    ds, ax
 inc    word ptr flag

 pop    ax
 pop    ds
 popf
       db 02Eh, 0EAh {cs:jmp 00000000}
@OI1Ch :
 dd     0
{ iret}
end;
{Восстаналиваем обработчик прерывания}
Procedure RestoreInt1Ch; Assembler;
asm
  push  ds
  lds   dx, OldInt1Ch
  mov   ax, 251Ch
  int   21h
  pop   ds
end;
{Процедуры и функции "интерфейсика"}
{Строит оси координат}
Procedure BuildScreen;
var
   i, j : Byte;
begin
  SetBkColor(Black);
  ClearViewPort;
  SetColor(DarkGray);
  MoveTo(0, 240);
  LineTo(640, 240);
  LineTo(630, 238);
  LineTo(630, 242);
  LineTo(640, 240);
  MoveTo(320, 480);
  LineTo(320, 0);
  LineTo(318, 10);
  LineTo(322, 10);
  LineTo(320,0);
  SetColor(LightGray);
  for i := 1 to 32 do Line(i*20, 239, i*20, 241);
  for i := 1 to 24 do Line(319, i*20, 321, i*20);
  SetColor(Brown);
  OutTextXY(324, 230, '0');
  OutTextXY(632, 230, 'x');
  OutTextXY(324, 3, 'y');
end;
{Рисует белый треугольник и красную точку. А также выводит сообщение}
{о положении точки}
Procedure DrawTrig;
var
  i : Word;
begin
  SetColor(White);
  SetWriteMode(XORPut);
  WaitRetrace;
  HideMouse;
  MoveTo(xp[1], yp[1]);
  LineTo(xp[2], yp[2]);
  LineTo(xp[3], yp[3]);
  LineTo(xp[1], yp[1]);
  MoveTo(x_[1], y_[1]);
  LineTo(x_[2], y_[2]);
  LineTo(x_[3], y_[3]);
  LineTo(x_[1], y_[1]);
  SetColor(LightRed);
  MoveTo(xp[0], yp[0]);
  LineTo(xp[0], yp[0]);
  MoveTo(x_[0], y_[0]);
  LineTo(x_[0], y_[0]);
  ShowMouse;
  for i := 0 to 3 do
  begin
    xp[i] := x_[i];
    yp[i] := y_[i];
  end;
  SetWriteMode(NormalPut);
  SetColor(Black);
  SetFillStyle(1, 0);
  Bar(0,469,200,479);
  SetColor(LightBlue);
  case WhereDot of
   0: OutTextXY(1,469,'На стороне треугольника');
   1: OutTextXY(1,469,'Внутри треугольника');
   2: OutTextXY(1,469,'Снаружи треугольника');
  end;
end;
{Осуществляет перемещение точки (при нажатии левой кнопки)}
{и перемещение координат вершин треугольника (при нажатии правой на вершине)}
Procedure MoveTrigDot(k : Word);
var
  Mx, My : Integer;
begin
 While MouseButt<>0 do
 begin
   if Mx <> MouseX then
   begin
     x_[k] := MouseX;
     x[k] := (x_[k]-320)/Sx;
     y[k] := (240 - y_[k])/Sy;
     DrawTrig;
   end;
   if My <> MouseY then
   begin
     y_[k] := MouseY;
     x[k] := (x_[k]-320)/Sx;
     y[k] := (240 - y_[k])/Sy;
     DrawTrig;
   end;
   Mx := MouseX;
   My := MouseY;
 end;
 x[k] := (x_[k]-320)/Sx;
 y[k] := (240 - y_[k])/Sy;
 DrawTrig;
end;
{Основная программа}
begin
  D := Detect;
  InitGraph(D, R, '');
  e := GraphResult;
  if e <> 0 then
   begin
     WriteLn('Ошибка при установлении графического режима!');
     WriteLn('В папке с программой (demotrig.exe) должен находиться файл EGAVGA.BGI');
     WriteLn(GraphErrorMsg(e));
   end;
  SetInt1Ch;
  InitMouse;
  x[0] := 0;
  y[0] := 0;
  x[1] := 1;
  y[1] := 1;
  x[2] := 1;
  y[2] := -1;
  x[3] := -1;
  y[3] := 0;
  for i := 0 to 3 do
  begin
   x_[i] := 320 + Round(Sx*x[i]);
   y_[i] := 240 - Round(Sy*y[i]);
  end;
  BuildScreen;
  ShowMouse;
  DrawTrig;
  While not KeyPressed do
  begin
   if MouseButt = 2 then
    begin
     for i := 1 to 3 do
      if MouseIn(xp[i]-2, yp[i]-2, xp[i]+2, yp[i]+2) then MoveTrigDot(i);
    end;
   if MouseButt = 1 then MoveTrigDot(0);
  end;
  ReadKey;
  HideMouse;
  RestoreInt1Ch;
  CloseGraph;
end.

Назад