Состав и структура программы

 

В состав программы входят следующие модули:

– пользовательский интерфейс;

– модуль создания линий;

– модуль определения положения точки;

– модуль определения положения фигуры;

– модуль определения топологического отношения;

 

В модуле создания линий по заданным точкам высчитываются коэффициенты k и b для прямых заданных уравнением и записываются в динамический массив lines типа TMas_L, определенного программистом.

В модуле определения положения точки используется функция «figure_vo», которая определяет количество точек одной фигуры, принадлежащих другой фигуре и функция «figure_nr», определяющая количество точек одной фигуры принадлежащих ребрам другой фигуры.

В модуле определения положения фигуры используется функция «proverka», которая определяет положение каждой фигуры относительно другой

В модуле определения топологического отношения используется функция «res», определяющая конечный результат, основываясь на том, какой результат получился при выполнении модуля определения положения фигуры.

 

После запуска приложения появляется основная форма, содержащая меню, Radiogroup для выбора фигуры, кнопку «Добавить точку», кнопку «Показать результат» и поле для отображения введенных точек.

При нажатии на кнопку «Добавить точку», появляется форма с полями для ввода координат и кнопкой «Добавить».

При нажатии на кнопку «Показать результат» (при введенных значениях), появляется форма с графиком и полем с результатом.

Кнопка «Очистить» из Меню удаляет информацию о введенных точках.

Кнопка «О программе» показывает форму с информацией о программном продукте и его разработчиках.

Кнопка «Выход» закрывает приложение.

 

Используемые технические средства

  1. PC
  2. Мышь
  3. Клавиатура

Вызов и загрузка

 

Вызов программы осуществляется выполнением приложения PrgTopology, которое находится в папке «Основной проект»

 

 

 

Входные данные:

Координаты точек каждой из фигур (Вводятся в StringGrid). Координаты должны быть целочисленные. Хотя пользователь при вводе координат точки, не сможет ввести вещественные и отрицательные числа, так как сработает защита от «дураков», с помощью которой возможно избежать некоторые ошибки.

 

Инструкция пользователя

1. После запуска приложения, пользователь видит основную форму для ввода данных

 

Пользователь выбирает координаты точек, какой фигуры он собирается задать и нажимает на кнопку «Добавить точку»

2.

 
 

Пользователь видит перед собой форму с полями для ввода координат и кнопкой «Добавить»

 

3. Пользователь вводит координаты для необходимого количества точек, используя символы от 0 до 9, строго в той последовательности, в которой они должны будут соединяться (возможен ввод по часовой и против, результат одинаковый).

4.
После того, как пользователь ввел координаты точек первой фигуры, он выбирает вторую фигуру и таким же образом добавляет точки для нее.

 

5. После того, как все точки добавлены, пользователь нажимает на кнопку «Просмотр результата»

 
 

6.
И видит перед собой форму, на которой выведен результат и его визуальное представление в виде графика с фигурами в соответствующем масштабе

 

7. После получения результата пользователь закрывает окно с графиком и возвращается к основной форме. Далее он может очистить поля для ввода значений точек (Файл – очистить или же комбинация «горячих» клавиш: Ctrl+A) и проверить другие фигуры.

8.

 
 

Так же пользователь имеет возможность подробнее узнать о программе и её разработчиках, нажав «О программе»

 

9. Пользователь может закрыть программу несколькими способами:

 

1) Нажав на «крестик» в правом верхнем углу

 

2) Нажав «Выход» (Файл – Выход)

 

3) Нажав комбинацию «горячих» клавиш: Ctrl+Q

 

Выходные данные:

Результат проверки, в виде текста («Наложение», «Вложена», «Примыкает», «Не пересекаются)

Визуальное представление результата в виде контуров заданных фигур, изображенных в первой четверти координатных осей.

 

Приложение

unit Unit1;

 

interface

 

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, StdCtrls, ExtCtrls, Menus, Grids, XPMan, Math;

 

type

TForm1 = class(TForm)

select_figure: TRadioGroup;

StringGrid1: TStringGrid;

StringGrid2: TStringGrid;

Label1: TLabel;

Label2: TLabel;

MainMenu1: TMainMenu;

N1: TMenuItem;

N2: TMenuItem;

Button_addpoint: TButton;

XPManifest1: TXPManifest;

ButtonStart: TButton;

N3: TMenuItem;

N4: TMenuItem;

procedure Button_addpointClick(Sender: TObject);

procedure FormActivate(Sender: TObject);

procedure ButtonStartClick(Sender: TObject);

procedure N4Click(Sender: TObject);

procedure N3Click(Sender: TObject);

procedure N2Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

 

var

Form1: TForm1;

 

implementation

 

uses Unit2, Unit3, Unit4;

 

{$R *.dfm}

type

 

//параметры каждой прямой!

TLine = record

x0,x1 :double; //промежуток, на котором задана прямая

k,b: double; //коэффициенты прямой

end;

 

//координаты точки

TPoints = record //запись для точки

x,y:double;

end;

 

TMas_L=array of TLine; //типы данных определенные программистом

TMas_P=array of TPoints;

 

const

eps=-10;

 

var

lines: TMas_L; //основной массив прямых

points: TMas_P; //массив для входных точек

num1, num2:integer; //количество точек (прямых)

teta:double;//угол поворота

 

 

procedure CreateLine (points:TMas_P; n1,n2:integer); //создание прямых по точкам

var

i:integer; //переменные для циклов

begin

 

SetLength(lines,n1+n2); //определение количества прямых

 

for i:=0 to n1-1 do

if i<>n1-1 then

begin

if points[i].x < points[i+1].x then

begin

lines[i].x0:=points[i].x;

lines[i].x1:=points[i+1].x;

end

else

begin

lines[i].x0:=points[i+1].x;

lines[i].x1:=points[i].x;

end;

 

lines[i].k:=(points[i+1].y-points[i].y)/(points[i+1].x-points[i].x);

lines[i].b:=points[i].y - points[i].x*lines[i].k;

 

end

else

begin

if points[i].x > points[0].x then

begin

lines[i].x0:=points[0].x;

lines[i].x1:=points[i].x;

end

else

begin

lines[i].x0:=points[i].x;

lines[i].x1:=points[0].x;

end;

lines[i].k:=(points[0].y-points[i].y)/(points[0].x-points[i].x);

lines[i].b:=points[i].y - points[i].x*lines[i].k;

end;

 

 

for i:=n1 to n1+n2-1 do

if i<>n1+n2-1 then

begin

if points[i].x < points[i+1].x then

begin

lines[i].x0:=points[i].x;

lines[i].x1:=points[i+1].x;

end

else

begin

lines[i].x0:=points[i+1].x;

lines[i].x1:=points[i].x;

end;

 

lines[i].k:=(points[i+1].y-points[i].y)/(points[i+1].x-points[i].x);

lines[i].b:=points[i].y - points[i].x*lines[i].k;

 

end

else

begin

if points[i].x > points[n1].x then

begin

lines[i].x0:=points[n1].x;

lines[i].x1:=points[i].x;

end

else

begin

lines[i].x0:=points[i].x;

lines[i].x1:=points[n1].x;

end;

lines[i].k:=(points[n1].y-points[i].y)/(points[n1].x-points[i].x);

lines[i].b:=points[i].y - points[i].x*lines[i].k;

end;

 

 

end;

//*************************************************************************************************

function figure_vo(lines:TMas_L; n1, n2: integer; x,y:double):boolean; //функция проверки есть ли нужное пересечение

var

i:integer;

fx,fi:boolean;

begin

figure_vo:=false;

fx:=false;

fi:=false;

 

for i:=n1 to n2-1 do

begin

if i<>n2-1 then

begin

if simpleroundto(lines[i].x1,eps)=simpleroundto(lines[i+1].x0,eps) then

if (simpleroundto(x,eps) <= simpleroundto(lines[i].x1,eps)) and (simpleroundto(x,eps) >simpleroundto(lines[i].x0,eps)) then

begin

if (simpleroundto(y,eps) < simpleroundto(lines[i].k*x + lines[i].b,eps)) then fx:=not(fx);

if (simpleroundto(y,eps) > simpleroundto(lines[i].k*x + lines[i].b,eps)) and (simpleroundto(x,eps)<>simpleroundto(lines[i].x1,eps)) then fi:=not(fi);

if fx and fi then begin figure_vo:=true; exit; end;

end;

 

if simpleroundto(lines[i].x0,eps)=simpleroundto(lines[i+1].x1,eps) then

if (simpleroundto(x,eps) < simpleroundto(lines[i].x1,eps)) and (simpleroundto(x,eps) >=simpleroundto(lines[i].x0,eps)) then

begin

if (simpleroundto(y,eps) < simpleroundto(lines[i].k*x + lines[i].b,eps)) then fx:=not(fx);

if (simpleroundto(y,eps) > simpleroundto(lines[i].k*x + lines[i].b,eps)) and (simpleroundto(x,eps)<>simpleroundto(lines[i].x0,eps)) then fi:=not(fi);

if fx and fi then begin figure_vo:=true; exit; end;

end;

 

if simpleroundto(lines[i].x1,eps)=simpleroundto(lines[i+1].x1,eps) then

if (simpleroundto(x,eps) <= simpleroundto(lines[i].x1,eps)) and (simpleroundto(x,eps) >simpleroundto(lines[i].x0,eps)) then

begin

if (simpleroundto(y,eps) < simpleroundto(lines[i].k*x + lines[i].b,eps)) then fx:=not(fx);

if (simpleroundto(y,eps) > simpleroundto(lines[i].k*x + lines[i].b,eps)) and (simpleroundto(x,eps)<>simpleroundto(lines[i].x1,eps)) then fi:=not(fi);

if fx and fi then begin figure_vo:=true; exit; end;

end;

 

if simpleroundto(lines[i].x0,eps)=simpleroundto(lines[i+1].x0,eps) then

if (simpleroundto(x,eps) < simpleroundto(lines[i].x1,eps)) and (simpleroundto(x,eps) >=simpleroundto(lines[i].x0,eps)) then

begin

if (simpleroundto(y,eps) < simpleroundto(lines[i].k*x + lines[i].b,eps)) then fx:=not(fx);

if (simpleroundto(y,eps) > simpleroundto(lines[i].k*x + lines[i].b,eps)) and (simpleroundto(x,eps)<>simpleroundto(lines[i].x0,eps)) then fi:=not(fi);

if fx and fi then begin figure_vo:=true; exit; end;

end;

 

end

 

else

 

begin

if simpleroundto(lines[i].x1,eps)=simpleroundto(lines[n1].x0,eps) then

if (simpleroundto(x,eps) <= simpleroundto(lines[i].x1,eps)) and (simpleroundto(x,eps) >simpleroundto(lines[i].x0,eps)) then

begin

if (simpleroundto(y,eps) < simpleroundto(lines[i].k*x + lines[i].b,eps)) then fx:=not(fx);

if (simpleroundto(y,eps) > simpleroundto(lines[i].k*x + lines[i].b,eps)) and (simpleroundto(x,eps)<>simpleroundto(lines[i].x1,eps)) then fi:=not(fi);

if fx and fi then begin figure_vo:=true; exit; end;

end;

 

if simpleroundto(lines[i].x0,eps)=simpleroundto(lines[n1].x1,eps) then

if (simpleroundto(x,eps) < simpleroundto(lines[i].x1,eps)) and (simpleroundto(x,eps) >=simpleroundto(lines[i].x0,eps)) then

begin

if (simpleroundto(y,eps) < simpleroundto(lines[i].k*x + lines[i].b,eps)) then fx:=not(fx);

if (simpleroundto(y,eps) > simpleroundto(lines[i].k*x + lines[i].b,eps)) and (simpleroundto(x,eps)<>simpleroundto(lines[i].x0,eps)) then fi:=not(fi);

if fx and fi then begin figure_vo:=true; exit; end;

end;

 

if simpleroundto(lines[i].x1,eps)=simpleroundto(lines[n1].x1,eps) then

if (simpleroundto(x,eps) <= simpleroundto(lines[i].x1,eps)) and (simpleroundto(x,eps) >simpleroundto(lines[i].x0,eps)) then

begin

if (simpleroundto(y,eps) < simpleroundto(lines[i].k*x + lines[i].b,eps)) then fx:=not(fx);

if (simpleroundto(y,eps) > simpleroundto(lines[i].k*x + lines[i].b,eps)) and (simpleroundto(x,eps)<>simpleroundto(lines[i].x1,eps)) then fi:=not(fi);

if fx and fi then begin figure_vo:=true; exit; end;

end;

 

if simpleroundto(lines[i].x0,eps)=simpleroundto(lines[n1].x0,eps) then

if (simpleroundto(x,eps) < simpleroundto(lines[i].x1,eps)) and (simpleroundto(x,eps) >=simpleroundto(lines[i].x0,eps)) then

begin

if (simpleroundto(y,eps) < simpleroundto(lines[i].k*x + lines[i].b,eps)) then fx:=not(fx);

if (simpleroundto(y,eps) > simpleroundto(lines[i].k*x + lines[i].b,eps)) and (simpleroundto(x,eps)<>simpleroundto(lines[i].x0,eps)) then fi:=not(fi);

if fx and fi then begin figure_vo:=true; exit; end;

end;

end;

end;

end;

 

function figure_nr(lines:TMas_L; n1, n2: integer; x,y:double):boolean; //функция проверки есть ли нужное пересечение

var

i:integer;

begin

figure_nr:=false;

for i:=n1 to n2-1 do

if (simpleroundto(x,eps) <= simpleroundto(lines[i].x1,eps)) and (simpleroundto(x,eps) >= simpleroundto(lines[i].x0,eps)) and (simpleroundto(y,eps) = simpleroundto((lines[i].k*x + lines[i].b),eps)) then begin figure_nr:=true; exit; end;

end;

 

 

function proverka(nl,vo,nr:integer;flag,flagindex:boolean):string;

begin

//условия, при выполнении которых можно сделать вывод

proverka:='';

if (nl>0) and (nr>=0) and (vo>=0) and (flag) then proverka:='Н';

if (nl>0) and ((nr>0) or (flagindex)) and (vo=0) and (flag=false) then proverka:='П';

if (nl=0) and ((vo>0) or (nr>0) or flagindex) and (flag=false) then proverka:='В';

if (nl>0) and (vo=0) and (nr=0) and (flag=false) and (flagindex=false) then proverka:='НП';

end;

 

function res(nl1,nl2,vo1,vo2,nr1,nr2:integer; flag, flagindex:boolean):string;

var str1,str2:string;

begin

str1:=proverka(nl1,vo1,nr1,flag,flagindex);

str2:=proverka(nl2,vo2,nr2,flag,flagindex);

if (str1='Н') or (str2='Н') then res:='Наложение';

if ((str1='В') or (str2='В')) and ((str1='П') or (str2='НП') or (str1='НП') or (str2='П') ) then res:='Вложена';

if (str1='НП') and (str2='НП') then res:='Не пересекаются';

if ((str1='П') and (str2='П')) then res:='Примыкает';

end;

//******************************************************************************

 

 

procedure TForm1.Button_addpointClick(Sender: TObject); //открытие формы для добавления точки

begin

Form2.Show;

end;

 

procedure TForm1.FormActivate(Sender: TObject); //нанесение поясительных записей в stringgrid

begin

stringgrid1.Cells[0,0]:='Имя';

stringgrid1.cells[1,0]:='X';

stringgrid1.Cells[2,0]:='Y';

stringgrid2.cells[0,0]:='Имя';

stringgrid2.cells[1,0]:='X';

stringgrid2.Cells[2,0]:='Y';

end;

 

procedure TForm1.ButtonStartClick(Sender: TObject);//запуск основной процедуры

var

i,j:integer;//переменная для цикла

 

vo1, nr1, nl1,vo2,nl2,nr2:integer; //счетчки для определения положения фигуры

 

x:double;//икс для дополнительного условия

 

flag,flagindex,flagvn:boolean; //флаг нахождения пересечения для дополнительного условия

 

fl1,fl2:integer;//флаги возможного положения прямой внутри фигуры

 

begin

teta:=20;//коэффициент для афинного преобразования

form2.Close;//закрытие формы ввода

form3.show;//показ формы с графиком

//флажки пересечения

flag:=false;

flagindex:=false;

//обнуление счетчиков

vo1:=0;

nr1:=0;

nl1:=0;

vo2:=0;

nr2:=0;

nl2:=0;

//присвоение точек в массив**************************************************

num1:=Stringgrid1.rowcount-1;

num2:=Stringgrid2.rowcount-1;

 

SetLength(points,num1+num2);

//преобразование и ввод координат точек

for i:=0 to num1-1 do

begin

points[i].x:=StrToFloat(stringgrid1.Cells[1,i+1]) + teta*StrToFloat(stringgrid1.Cells[2,i+1]);

points[i].y:=StrToFloat(stringgrid1.Cells[2,i+1]);

end;

 

for i:=num1 to (num1+num2)-1 do

begin

points[i].x:=StrToFloat(stringgrid2.Cells[1,i+1-num1]) + teta*StrToFloat(stringgrid2.Cells[2,i+1-num1]);

points[i].y:=StrToFloat(stringgrid2.Cells[2,i+1-num1]);

end;

//******************************************************************************

 

CreateLine(points,num1,num2);//создание прямых по точкам

 

for i:=0 to num1-1 do //используется для проверки пересечения прямых. Тем самым выполняется ли условие наложенности

begin

for j:=num1 to num1+num2-1 do

begin

if simpleroundto(lines[i].k,eps)<>simpleroundto(lines[j].k,eps) then

begin

x:=(lines[i].b-lines[j].b)/(lines[j].k-lines[i].k); //решение уравнения

if (simpleroundto(x,eps)<simpleroundto(lines[i].x1,eps)) and (simpleroundto(x,eps)>simpleroundto(lines[i].x0,eps)) and (simpleroundto(x,eps)<simpleroundto(lines[j].x1,eps)) and (simpleroundto(x,eps)>simpleroundto(lines[j].x0,eps))then flag:=true;

end;

//линия лежит на линии другой фигуры

if ((simpleroundto(lines[i].k,eps)=simpleroundto(lines[j].k,eps)) and (simpleroundto(lines[i].b,eps)=simpleroundto(lines[j].b,eps))) and (((simpleroundto(lines[i].x0,eps)>=simpleroundto(lines[j].x0,eps)) and (simpleroundto(lines[i].x1,eps)<=simpleroundto(lines[j].x1,eps))) or ((simpleroundto(lines[i].x0,eps)<=simpleroundto(lines[j].x0,eps)) and (simpleroundto(lines[i].x1,eps)>=simpleroundto(lines[j].x1,eps)))) then flagindex:=true;

 

end;

end;

 

 

for i:=0 to num1-1 do //проверка расположения второй относительно точек первой

begin

if figure_nr(lines,num1,num1+num2,points[i].x,points[i].y) then nr1:=nr1+1

else if figure_vo(lines,num1,num1+num2,points[i].x,points[i].y) then vo1:=vo1+1

else nl1:=nl1+1;

end;

 

for i:=num1 to num1+num2-1 do //проверка первой относительно точек второй

begin

if figure_nr(lines,0,num1,points[i].x,points[i].y) then nr2:=nr2+1

else if figure_vo(lines,0,num1,points[i].x,points[i].y) then vo2:=vo2+1

else nl2:=nl2+1;

end;

 

 

form3.Label1.caption:=res(nl1,nl2,vo1,vo2,nr1,nr2,flag,flagindex);//вывод окнчательного вердикта о расположении

 

end;

 


[1] Код программы на алгоритмическом языке находится в разделе Приложение