Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Математическое моделирование - Никишев.doc
Скачиваний:
175
Добавлен:
20.03.2016
Размер:
7.18 Mб
Скачать

Пример Моделирование системы планирования на основе метода сетевого графа

Задачи исследования

Необходимо спланировать временный график работ в соответствии с графом и вычислить критический путь выполнения всех работ

Исходные данные

Задание:Дана схема, нужно найти критический путь

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

Условие.Пусть предприятие производит столы и стулья. Расход ресурсов на их производство и прибыль от их реализации представлены в таблице. столы стулья объем ресурсов

Расход древесины

на изделие, м3 0,5 0,04 200

Расход труда(чел-час) 12 0,6 1800

Прибыль от реализации

единицы изделия , руб 180 20

Кроме того на производство 80 столов имеется заказ с министерством

Уравнения1-количество столов х2 - количество стульев

0,5 х1 + 0,04х2<=200

12x1 + 0,6x2 <=18000

x1+20x2 =max ( целевая функция)

unit

Unit4;

procedure TForm4.Button3Click(Sender: TObject);

begin

close();

end;

procedure TForm4.Button1Click(Sender: TObject);

begin

form1.visible:=true;

form4.visible:=false;

end;

function Fy(x:real): real;

begin

Fy := (60-6*x)/4;

end;

function Fx(x:real): real;

begin

Fx :=(100+2*x)/10;

end;

procedure TForm4.Button2Click(Sender: TObject);

var a, b ,h, x1, y, x2: Double;

begin

Chart1.Series[0].Clear;

Chart1.Series[1].Clear;

Chart1.Series[2].Clear;

a := StrToFloat(LabeledEdit1.Text); //левая граница

b := StrToFloat(LabeledEdit2.Text); //правая граница

h := StrToFloat(LabeledEdit3.Text); //шаг

x1 := a;

repeat

y := Fy(x1);

x2 := Fx(y);

hart1.Series[0].AddXY(x1,y,FloatToStrF(x1,ffGeneral,4,3),clRed); //график F(x)

hart1.Series[1].AddXY(x2,y,FloatToStrF(y,ffGeneral,4,3),clGreen); //график F(y)

x1 := x1 + h; //приращение координат

until x1 > b;

x1 := a;

repeat

y := Fy(x1);

x2 := Fx(y);

x1 := x1 + h/10000;

if ( x1 < x2 + h/10000 ) and ( x1 > x2 - h/10000 ) then

begin

Label5.Caption := 'Решение: ' +#13+ 'x = '+FloatToStrF(x1,ffGeneral,7,7)+#13;

Label5.Caption :=Label5.Caption + 'y = '+FloatToStrF(y,ffGeneral,7,7);

Chart1.Series[2].AddXY(x1,y,FloatToStrF(x1,ffGeneral,4,3),clBlue);

end;

until x1 > b;

end;end.

2.9 Лабораторная работа

Тема: Исследование вероятностных систем ( систем массового обслуживания) с использованием различных информационных технологий.

Цель занятия: Получить практические навыки исследования систем ( объектов) с вычислением параметров статистических моделей и определением эффективности исследуемых систем с использованием языков программирования : Delphi, VC++, VC# и информационных технологий MatLab,Scilab..

Задачи занятия:

1. Разработка алгоритмов

2. Разработка программы исследования различных систем

3. Анализ результатов исследований с вычислением параметров и эффективности систем.

Задания для исследований в разделе Задания

Пример 1. Исследовать параметры обслуживания покупателей в магазине с одним продавцом

Программа на Делфи

unit Unit2;

function f(x:real;g:real;h:real):real;

begin

f:=(1/(g*sqrt(3.14*2)))*(power(exp(1),(((x-h)*(x-h))/(-2*g*g)))); // нормальный закон распределения

end;

procedure TForm2.Button2Click(Sender: TObject);

var n,i,a,b,rk:integer;

g,h,f1,fn,h1,x1,sr,t,y,kol,vrop:real;

begin

randomize;

g:=strtofloat(edit1.text); // среднеквадратич отклонение X

h:=strtofloat(edit2.text);//мат ожидание

Chart1.Series[0].Clear; //очистка графика

a:=StrToint(Edit4.Text); //левая граница

b:=StrToint(Edit5.Text); //правая граница

h1:=0.1;

x1:=a;

n:=1;

fn:=0;

t:=h1;

stringgrid1.Cells[0,0]:='x';

stringgrid1.Cells[1,0]:='f(x)';

repeat

f1:=f(x1,g,h);

Chart1.Serieslist[0].AddXY(x1,f1,'',clRed); //график F(x)

stringgrid1.Cells[0,n]:=floattostr(x1);

stringgrid1.Cells[1,n]:=floattostr(f1);

x1:=x1+h1;

n:=n+1;

fn:=f1+fn;

stringgrid1.RowCount:=n+1;

until x1>b;

kol:=(b-a)*60*g;

edit6.text:=floattostr(kol);

rk:=strtoint(edit6.text);

i:=random(rk);

edit7.text:=inttostr(random(5));

sr:=strtofloat(edit7.text);

vrop:=((b-a)*60-sr*kol)/kol;

if vrop>=0 then

edit8.Text:=floattostr(((b-a)*60-sr*kol)/kol)

else edit8.Text:='0';

if vrop<=0 then

edit3.Text:=floattostr(-vrop) else

edit3.Text:='0';

edit6.text:=floattostr(i);

end;

end.

2.9

unit Unit3;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, Menus, ExtCtrls, StdCtrls, jpeg;

type

TForm3 = class(TForm)

MainMenu1: TMainMenu;

N1: TMenuItem;

N2: TMenuItem;

Timer1: TTimer;

GroupBox1: TGroupBox;

Edit1: TEdit;

Edit2: TEdit;

Edit3: TEdit;

Edit4: TEdit;

Edit5: TEdit;

Label1: TLabel;

Label2: TLabel;

Label3: TLabel;

Label4: TLabel;

Label5: TLabel;

Timer2: TTimer;

Image1: TImage;

N3: TMenuItem;

Image2: TImage;

Label6: TLabel;

procedure N2Click(Sender: TObject);

procedure Timer1Timer(Sender: TObject);

procedure N1Click(Sender: TObject);

procedure Timer2Timer(Sender: TObject);

procedure N3Click(Sender: TObject);

var

Form3: TForm3;

a,b,t,kol,za,k,i,l,j,ll,gdet,zanvr:Integer;

nach,vrem,kon,pokgdet,pok,x1,y1:Integer;

Buyx,Buyy:Integer;

obsl,prish:Integer;

tekvr,chas,minut:String;

pokin:array[1..1000] of real;

pokvr1:array[1..1000] of real;

pokvr:array[1..1000] of real;

prod:array[1..1000] of real;

ogid:array[1..1000] of real;

ob:array[1..1000] of real;

p,s,inte,buy,x,y,maxt,tt,vr:real;

implementation

uses Unit2, Unit1;

procedure TForm3.N2Click(Sender: TObject);

begin

form3.Hide;

form1.show;

end;

procedure TForm3.Timer1Timer(Sender: TObject);

begin

If zanvr=prod[k] Then {если пок-ля обслужили}

begin

timer2.Enabled:=true;

image1.Visible:=true;

timer2.Interval:=100;

zanvr:=0;

k:=k+1;

If ogid[k]=0 Then {если пок-ль не в очереди}

begin

za:=za+1; {увеличиваем кол-во пришедших}

edit4.Text:=inttostr(za);

end;

If kol>0 Then begin

kol:=kol-1; {уменьшаем кол-во ждущих в очереди}

edit5.Text:=inttostr(kol);

form3.Canvas.Pen.Color:=clskyblue;

form3.Canvas.Brush.Color:=clskyblue;

form3.Canvas.Ellipse(x1,y1,x1+30,y1+30);

x1:=x1-32;

end;

obsl:=obsl+1; {увел-м кол-во обслуженных}

edit2.Text:=inttostr(obsl);

end;

buy:=pokvr[k];

If buy=i Then begin {если покупатель пришел}

zanvr:=zanvr+1; {начинаем обслуживать}

pokvr[k]:=i+1;

end

Else gdet:=gdet+1; {иначе увел-ся простой продавца}

For j:=k+1 To l-1 do

begin

x:=pokvr[j];

y:=pokvr[k];

If x<y Then begin {если еще есть пришедшие}

pokvr[j]:=pokvr[k];

If ogid[j]=0 Then begin

kol:=kol+1; {увел-м кол-во ждущих}

edit5.Text:=inttostr(kol);

x1:=x1+32;

form3.Canvas.Pen.Color:=clmaroon;

form3.Canvas.Brush.Color:=clmaroon;

form3.Canvas.Ellipse(x1,y1,x1+30,y1+30);

{увел-м кол-во пришедших}

za:=za+1;

edit4.Text:=inttostr(za);

ogid[j]:=1;

end;

end;

end;

i:=i+1; {увеличиваем время}

{преобразуем время в часы и минуты}

str((i div 60),chas);

str((i mod 60),minut);

tekvr:=chas+':'+minut;

edit1.Text:=tekvr;

edit3.Text:=inttostr(gdet);

if i>=kon then timer1.Enabled:=false;

end;

procedure TForm3.N1Click(Sender: TObject);

var stroka,stroka1:string;

begin

For i:=1 To obsl do

begin

ob[i]:=pokvr[i]-prod[i]-pokvr1[i];

s:=s+ob[i];

end;

For i:=obsl+1 To l-1 do {суммируем время ожидания в оч-ди}

begin

ob[i]:=pokvr[i]-pokvr1[i];

s:=s+ob[i];

end;

s:=s/(l-1); {находим среднее арифметич-ое}

stroka1:=inttostr(gdet);

stroka:=inttostr(round(s));

showmessage('Среднее время ожидания в очереди покупателем равно'+stroka+'минут; простой продавца в ожидании прихода покупателей'+stroka1+'минут');

end;

procedure TForm3.Timer2Timer(Sender: TObject);

begin

Image1.Left:=Image1.Left-30;

If Image1.Left<112 Then begin

Timer2.Enabled:=False;

Image1.Visible:=False;

Image1.Left:=208;

End;

end;

procedure TForm3.N3Click(Sender: TObject);

begin

nach:=strtoint(form2.edit1.Text)*60;

inte:=strtofloat(form2.Edit3.Text);

kon:=strtoint(form2.edit2.Text)*60;

pok:=0;

gdet:=1;

k:=0;

zanvr:=0;

vrem:=0;

obsl:=0;

i:=1;

vr:=nach;

gdet:=0;

k:=1;

x1:=290;

y1:=140;

maxt:=random(5); {максимальное время}

maxt:=(maxt+1)/100;

While vr<kon do

begin {интервал прихода покупателей}

pokin[i]:=random(7); {в соответствии с функцией Пуассона}

pokin[i]:=Int((1/inte)*((pokin[i]+1)/10))+1;

tt:=(inte*pokin[i])*(exp((-inte*pokin[i])*ln(2.71)));

If tt>maxt Then

begin

vr:=vr+pokin[i];

pokvr[i]:=vr; {время прихода пок-лей}

pokvr1[i]:=vr;

i:=i+1;

end;

end;

For l:=1 To i do

begin {время, кот. тратит продавец}

prod[l]:=random(8);

prod[l]:=Int((1/inte)*((prod[l]+1)/10))+1;

ob[l]:=0;

ogid[l]:=0;

end;

i:=nach;

timer1.enabled:=true;

timer1.interval:=500;

end;

end.

Тема: Исследование оптимальных ( имитационных) систем Цель занятия: Получить практические навыки исследования оптимальных ( имитационных) систем

Задачи занятия:

1. Разработка алгоритмов

2. Разработка программы исследования различных систем

3. Анализ результатов исследований с вычислением параметров

unit Unit1;

interface

usesWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;

var

Form1: TForm1;

dx,dy:real; //масштаб реки K_Der,D_Reki,N_R,D_Reki1,N_R1,R,i,num,mmx,rast,j,mmn,x,y,xv,yv,xn,yn:integer;

St:array[1..800,1..2] of integer; //длина реки

Pl:array[1..100,1..2] of integer; //количество деревень

Rw:array[1..2,1..2] of integer; //река

implementation

uses Unit2;

procedure TForm1.Button1Click(Sender: TObject);

begin

form1.Hide;

form2.show;

end;

procedure TForm1.Button2Click(Sender: TObject);

begin

xv:=strtoint(inputbox('vvod ','1-ая координата левого верхнего угла поля(0-10)',''));

yv:=strtoint(inputbox('vvod ','2-ая координата левого верхнего угла поля(0-10)',''));

xn:=strtoint(inputbox('vvod ','1-ая координата правого нижнего угла поля(580-650)',''));

yn:=strtoint(inputbox('vvod ','2-ая координата правого нижнего угла поля(500-580)',''));

K_Der:=strtoint(inputbox('vvod ','количество деревень(1-70)',''));

D_Reki:=strtoint(inputbox('vvod ','длина реки(300-550)',''));

N_R:=strtoint(inputbox('vvod ','начало реки(10-200)',''));

{D_Reki1:=strtoint(inputbox('vvod ','длина реки(300-550)',''));

N_R1:=strtoint(inputbox('vvod ','начало реки(10-200)',''));}

R:=strtoint(inputbox('vvod ','длина разбиения(10-20)',''));

randomize;

for i:=1 to K_Der do begin //определение координат деревень

Pl[i,1]:=random(570)+10;

Pl[i,2]:=random(480)+10;

end;

Rw[1,1]:=N_R; //координаты реки

Rw[1,2]:=D_Reki;

Rw[2,1]:=random(480)+10;

Rw[2,2]:=random(480)+10;

end;

procedure TForm1.Button3Click(Sender: TObject);

begin

form1.Canvas.Brush.Color:=clolive; //вывод поля

form1.Canvas.Rectangle(xv,yv,xn,yn);

dx:=D_Reki/(D_Reki-1); //определение масштаба по реке

dy:=(Rw[2,2]-Rw[2,1])/(D_Reki-1);

form1.Canvas.Pen.Color:=clblue;

form1.Canvas.MoveTo(Rw[1,1],Rw[2,1]-3); //вывод реки на экран

form1.Canvas.LineTo(Rw[1,2],Rw[2,2]-3);

form1.Canvas.MoveTo(Rw[1,1],Rw[2,1]+3);

form1.Canvas.LineTo(Rw[1,2],Rw[2,2]+3);

for j:=1 to D_Reki do begin //определение расстояния до деревень

mmx:=0;

for i:=1 to K_Der do begin

rast:=round(sqrt(sqr(10+ dx*(j-1)-Pl[i,1])+sqr(Rw[2,1]+dy*(j-1)-Pl[i,2])));

if mmx<rast then begin

mmx:=rast; //максимальное из расстояний до деревень

St[j,1]:=rast;

end;end;

end;

for i:=1 to K_Der do begin

form1.Canvas.Brush.Color:=clyellow; //вывод деревень с их нумерацией

form1.Canvas.Pen.Color:=clred;

form1.Canvas.TextOut(Pl[i,1]-14,Pl[i,2]-14,inttostr(i));

end;

end;

procedure TForm1.Button4Click(Sender: TObject);

begin

{mmn:=1000;

for i:=1 to (D_Reki-N_R) do begin}

while i<=(D_Reki-N_R) do begin

mmn:=1000;i:=i+R; //определение искомого места на реке

if St[i,1]<mmn then begin

mmn:=St[i,1];

num:=i+R;

end;end;

for j:=1 to K_Der do begin //вывод расстояний от искомого места до деревень

rast:=round(sqrt(sqr(10+ dx*(num-1)-Pl[j,1])+sqr(Rw[2,1]+dy*(num-1)-Pl[j,2])));

form1.Canvas.Brush.Color:=clsilver;

form1.Canvas.Pen.Color:=clred;

form1.Canvas.TextOut(Pl[j,1]-3,Pl[j,2]-3,inttostr(rast));

end;

form1.Canvas.Pen.Color:=clfuchsia; //вывод искомого места

form1.Canvas.brush.Color:=clfuchsia;

form1.Canvas.Ellipse(round(dx*(num-R)+2),round(Rw[2,1]+dy*(num-R)-8),round(18+dx*(num-R)),round(Rw[2,1]+dy*(num-R)+8));

for i:=1 to K_Der do begin //линии от искомого места до деревень

form1.Canvas.Pen.Color:=clnavy;

form1.Canvas.brush.Color:=clnavy;

form1.Canvas.MoveTo(round(dx*(num-1)+7),round(Rw[2,1]+dy*(num-1)-5));

form1.Canvas.LineTo(Pl[i,1]-5,Pl[i,2]-5);end;

end;end.

unit Unit4;

interface

uses

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

Dialogs, StdCtrls, ExtCtrls;

type

TForm4 = class(TForm)

Button1: TButton;

GroupBox1: TGroupBox;

PaintBox1: TPaintBox;

LabeledEdit1: TLabeledEdit;

ListBox1: TListBox;

ListBox2: TListBox;

Button2: TButton;

Label1: TLabel;

Label2: TLabel;

GroupBox2: TGroupBox;

RadioButton1: TRadioButton;

RadioButton2: TRadioButton;

LabelMouse: TLabel;

procedure Button1Click(Sender: TObject);

procedure Button2Click(Sender: TObject);

procedure RadioButton2Click(Sender: TObject);

procedure RadioButton1Click(Sender: TObject);

procedure LabeledEdit1Change(Sender: TObject);

procedure PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,

Y: Integer);

procedure PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;

Shift: TShiftState; X, Y: Integer);

procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,

Y: Integer);

procedure FormShow(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

Type

PointType = record

x: Integer;

y: Integer;

end;

var

Form4: TForm4;

ReadMouse: Boolean;

MouseClickCount: Byte;

n: integer; { количество деревень }

i, j: integer; { для цикла }

MinOfAverages: integer; { минимальный средний путь до всех деревень }

iMinOfAverages: integer;

Average, AverVal: integer;

point: array[1..50] of PointType; { для записывания координат деревень }

z: array[1..50,1..50] of integer; { для записывания расстояний между деревнями }

Mx, My: integer;

implementation

uses Unit1;

{$R *.dfm}

procedure Vill( vX, vY, vI: Integer; clColor: TColor);

begin

Form4.PaintBox1.Canvas.Pen.Color := clColor;

Form4.PaintBox1.Canvas.Brush.Color := clColor;

Form4.PaintBox1.Canvas.Ellipse( vX - 10, vY - 10,

vX + 10, vY + 10 );

Form4.PaintBox1.Canvas.TextOut( vX-5, vY-6, IntToStr(vI) );

Form4.PaintBox1.Canvas.Brush.Color := clBtnFace;

Form4.PaintBox1.Canvas.TextOut( vX - 15, vY + 11,

IntToStr(vX) + ',' + IntToStr(vY) );

end;

//кнопка "Выполнить"

procedure TForm4.Button1Click(Sender: TObject);

begin

Form4.PaintBox1.Repaint;

if length( LabeledEdit1.Text ) > 0 then

n := StrToInt( LabeledEdit1.Text );

ListBox2.Clear;

{ цикл вычисления растояний между деревнями }

for i := 1 to n - 1 do

begin

for j := i + 1 to n do

begin

z[i,j] := trunc( sqrt( sqr( point[i].x - point[j].x ) +

sqr( point[i].y - point[j].y ) ) );

z[j,i] := z[i,j];

ListBox2.Items.Add( 'Путь между деревнями ' + IntToStr(i) + ' и ' + IntToStr(j) + ' : ' + IntToStr(z[i,j]) + ' км.' );

end;

z[i,i] := 0;

end;

MinOfAverages := 10000;

ListBox1.Clear;

{ вычисление пункта,из которого средний путь до всех деревень минимален }

for i := 1 to n do

begin

PaintBox1.Canvas.Pen.Color := clBlue;

AverVal := 0;

for j := 1 to n do

begin

AverVal := AverVal + z[i,j];

PaintBox1.Canvas.MoveTo( point[i].x, point[i].y );

PaintBox1.Canvas.LineTo( point[j].x, point[j].y );

end;

Average := trunc( AverVal / ( n - 1 ) );

PaintBox1.Canvas.Pen.Color := clYellow;

ListBox1.Items.Add( 'Среднй путь от деревни № ' + IntToStr(i) + ' : ' + IntToStr(Average) + ' км.' );

if Average < MinOfAverages then

begin

MinOfAverages := Average;

iMinOfAverages := i;

end;

end;

Label1.Caption := 'Минимальный средний путь: ' + IntToStr(MinOfAverages);

Label2.Caption := 'Номер деревни,где будет располагаться больница: ' + IntToStr(iMinOfAverages);

PaintBox1.Canvas.Pen.Color := clGreen;

PaintBox1.Canvas.Brush.Color := clGreen;

for i := 1 to n do

Vill( point[i].x, point[i].y, i, clGreen);

{ Найденный пункт выделяем другим цветом }

Vill( point[iMinOfAverages].x, point[iMinOfAverages].y, iMinOfAverages, clRed );

{ PaintBox1.Canvas.Pen.Color := clRed;

PaintBox1.Canvas.Brush.Color := clRed;

PaintBox1.Canvas.Ellipse( point[iMinOfAverages].x-10,

point[iMinOfAverages].y-10,

point[iMinOfAverages].x+10,

point[iMinOfAverages].y+10 );

PaintBox1.Canvas.TextOut( point[iMinOfAverages].x - 5,

point[iMinOfAverages].y - 6,

IntToStr( iMinOfAverages ) ); }

end;

//кнопка "Закрыть"

procedure TForm4.Button2Click(Sender: TObject);

begin

form4.Hide;

form1.show;

end;

procedure TForm4.RadioButton2Click(Sender: TObject);

begin

PaintBox1.Repaint;

MouseClickCount := 0;

ReadMouse := True;

Button1.Enabled := False;

end;

procedure TForm4.RadioButton1Click(Sender: TObject);

begin

PaintBox1.Repaint;

ReadMouse := False;

Button1.Enabled := True;

Randomize;

{ цикл генерирования и вывода координат деревень }

for i := 1 to n do

begin

point[i].x := trunc( random( Mx ) );

point[i].y := trunc( random( My ) );

Vill( point[i].x, point[i].y, i, clGreen );

end;

end;

procedure TForm4.LabeledEdit1Change(Sender: TObject);

begin

if length( LabeledEdit1.Text ) > 0 then

n := StrToInt( LabeledEdit1.Text );

PaintBox1.Repaint;

if RadioButton1.Checked then RadioButton1Click(Sender)

else RadioButton2Click(Sender);

end;

procedure TForm4.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,

Y: Integer);

begin

if ReadMouse then LabelMouse.Visible := True;

LabelMouse.Caption := IntToStr(X) + ',' + IntToStr(Y);

end;

procedure TForm4.PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;

Shift: TShiftState; X, Y: Integer);

begin

if ReadMouse then

begin

MouseClickCount := MouseClickCount + 1;

point[MouseClickCount].x := X;

point[MouseClickCount].y := Y;

Vill( X, Y, MouseClickCount, clGreen );

if MouseClickCount >= n then

begin

ReadMouse := False;

Button1.Enabled := True;

end;

end;

end;

procedure TForm4.FormMouseMove(Sender: TObject; Shift: TShiftState; X,

Y: Integer);

begin

LabelMouse.Visible := False;

end;

procedure TForm4.FormShow(Sender: TObject);

begin

Mx := PaintBox1.Width;

My := PaintBox1.Height;

Label1.Caption := '';

Label2.Caption := '';

RadioButton2.Checked := True;

RadioButton2Click(Sender);

LabeledEdit1Change(Sender);

end;

end.

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Windows.Forms;

namespace Lab7

{

public partial class FormSolution : Form

{

private Font drawFontArial10 = new Font("Arial", 10);

private SolidBrush drawBrushLightSkyBlue = new SolidBrush(Color.LightSkyBlue);

private SolidBrush drawBrushBlack = new SolidBrush(Color.Black);

private bool chooseStation1Toggle = false;

private bool chooseStation2Toggle = false;

private bool editRoadsToggle = false;

private PointF station1Point = new PointF(-10, -10);

private PointF station2Point = new PointF(-10, -10);

private Point minRoadToStation1Point;

private Point minRoadToStation2Point;

private Pen drawPenBlue3 = new Pen(Color.Blue, 3);

private Pen drawPenCrimson4 = new Pen(Color.Crimson, 4);

private Point midPoint;

private Point downPoint;

private Point upPoint;

private Point mirrorUpPoint;

private Point mirrorDownPoint;

private int currentAngle = 0;

private int totalDistance=0;

public FormSolution()

{

InitializeComponent();

midPoint.X = 200;

midPoint.Y = 200;

downPoint.X = 0;

downPoint.Y = 0;

upPoint.X = 0;

upPoint.Y = 0;

}

private void btn_exit_Click(object sender, EventArgs e)

{

this.Hide();

}

private void pb_MouseMove(object sender, MouseEventArgs e)

{

reDrawCanvas(new Point(e.X, e.Y));

}

private void reDrawCanvas(Point e)

{

pb.Refresh();

drawStations();

drawAngle();

drawRoads();

drawCurrentCoord(e.X, e.Y);

if ((station1Point.X >= 0) && (station2Point.X >= 0) && !((downPoint.X == 0) && (downPoint.Y == 0) && (upPoint.X == 0) && (upPoint.Y == 0)))

{

calculateAndDrawResult(station1Point, 1);

calculateAndDrawResult(station2Point, 2);

}

if (chooseStation1Toggle == true)

{

drawCircle(e.X, e.Y);

}

else if (chooseStation2Toggle == true)

{

drawCircle(e.X, e.Y);

}

if (editRoadsToggle == true)

{

drawEditRoad(e.X, e.Y);

}

}

private void drawRoads()

{

Graphics g = pb.CreateGraphics();

g.DrawLine(drawPenCrimson4, downPoint, upPoint);

g.DrawLine(drawPenCrimson4, mirrorDownPoint, mirrorUpPoint);

}

private void drawStations()

{

Graphics g = pb.CreateGraphics();

Rectangle drawRectC = new Rectangle(Convert.ToInt32(station1Point.X - 3), Convert.ToInt32(station1Point.Y - 3), 6, 6);

Pen drawPenRed = new Pen(Color.Red, 4);

g.DrawEllipse(drawPenRed, drawRectC);

String StringStation1 = "Пункт 1 (" + Convert.ToInt32(station1Point.X) + ":" + Convert.ToInt32(station1Point.Y) + ")";

g.DrawString(StringStation1, new Font("Arial", 7), drawBrushBlack, station1Point);

drawRectC = new Rectangle(Convert.ToInt32(station2Point.X - 3), Convert.ToInt32(station2Point.Y - 3), 6, 6);

Pen drawPenYellow = new Pen(Color.Yellow, 4);

g.DrawEllipse(drawPenYellow, drawRectC);

String StringStation2 = "Пункт 2 (" + Convert.ToInt32(station2Point.X) + ":" + Convert.ToInt32(station2Point.Y) + ")";

g.DrawString(StringStation2, new Font("Arial", 7), drawBrushBlack, station2Point);

}

private void drawCircle(int X, int Y)

{

Graphics g = pb.CreateGraphics();

Rectangle drawRect = new Rectangle(X - 3, Y - 3, 6, 6);

PointF drawPoint = new PointF(X - 70, Y - 10);

g.DrawEllipse(drawPenBlue3, drawRect);

String drawString;

if (chooseStation1Toggle == true)

{

drawString = "Пункт 1";

}

else

{

drawString = "Пункт 2";

}

g.DrawString(drawString, drawFontArial10, drawBrushBlack, drawPoint);

}

private void drawEditRoad(int X, int Y)

{

Graphics g = pb.CreateGraphics();

Point currentMousePoint = new Point(X, Y);

int upY = 0;

int downY = 400;

int upX=0;

int downX=0;

if (currentAngle <= 90)

{

upY = 0;

upX = lineDrawFormulaX(currentMousePoint, midPoint, upY);

downY = 400;

downX = lineDrawFormulaX(currentMousePoint, midPoint, downY);

}

else if (currentAngle > 90)

{

upX = 0;

upY = lineDrawFormulaY(currentMousePoint, midPoint, upX);

downX = 400;

downY = lineDrawFormulaY(currentMousePoint, midPoint, downX);

}

upPoint = new Point(upX, upY);

downPoint = new Point(downX, downY);

mirrorUpPoint = new Point(400 - upX, upY);

mirrorDownPoint = new Point(400 - downX, downY);

g.DrawLine(drawPenCrimson4, downPoint, upPoint);

g.DrawLine(drawPenCrimson4, mirrorDownPoint, mirrorUpPoint);

}

private void drawAngle()

{

if (!((upPoint.X==0) && (upPoint.Y==0)) || !((downPoint.X==0) && (downPoint.Y==0)))

{

Graphics g = pb.CreateGraphics();

PointF vector1 = new PointF(upPoint.X - downPoint.X, upPoint.Y - downPoint.Y);

PointF vector2 = new PointF(mirrorUpPoint.X - mirrorDownPoint.X, mirrorUpPoint.Y - mirrorDownPoint.Y);

double angle = Math.Acos((vector1.X * vector2.X + vector1.Y * vector2.Y) / (Math.Sqrt(Math.Pow(vector1.X, 2) + Math.Pow(vector1.Y, 2)) * Math.Sqrt(Math.Pow(vector2.X, 2) + Math.Pow(vector2.Y, 2))));

angle = angle * 180 / Math.PI;

currentAngle = Convert.ToInt32(angle);

Rectangle drawRect = new Rectangle(new Point(175,175),new Size(50,50));

int firstCircleAngle =((360 - Convert.ToInt32(angle) * 2) / 4);

g.DrawPie(drawPenBlue3, drawRect, firstCircleAngle, Convert.ToInt32(angle));

g.DrawString(Convert.ToInt32(angle) + "°", drawFontArial10, drawBrushBlack, new PointF(midPoint.X - 15, midPoint.Y + 25));

}

}

private int lineDrawFormulaX(Point po1, Point po2, int currentY)

{

try

{

return (currentY * po1.X - currentY * po2.X - 200 * po1.X + po2.X * po2.Y + po1.Y * po2.X - po2.X * po2.Y) / (po1.Y - po2.Y);

}

catch

{

return (currentY * po1.X - currentY * po2.X - 200 * po1.X + po2.X * po2.Y + po1.Y * po2.X - po2.X * po2.Y) / (po1.Y - 1 - po2.Y);

}

}

private int lineDrawFormulaY(Point po1, Point po2, int currentX)

{

try

{

return (po2.Y * currentX - po2.Y * po1.X - po1.Y * currentX + po1.Y * po1.X + po1.Y * po2.X - po1.Y * po1.X) / (po2.X - po1.X);

}

catch

{

return (po2.Y * currentX - po2.Y * po1.X - po1.Y * currentX + po1.Y * po1.X + po1.Y * po2.X - po1.Y * po1.X) / (po2.X - 1 - po1.X);

}

}

private void drawCurrentCoord(int X, int Y)

{

Graphics g = pb.CreateGraphics();

PointF drawPoint = new PointF(X, Y - 20);

String drawString = "(" + Convert.ToString(X) + " : " + Convert.ToString(Y) + ")";

g.DrawString(drawString, drawFontArial10, drawBrushLightSkyBlue, drawPoint);

}

private void btn_choose_station_1_Click(object sender, EventArgs e)

{

chooseStation1Toggle = true;

chooseStation2Toggle = false;

editRoadsToggle = false;

btn_choose_station_1.Enabled = false;

}

private void pb_MouseClick(object sender, MouseEventArgs e)

{

if (chooseStation1Toggle == true)

{

chooseStation1Toggle = false;

chooseStation2Toggle = false;

editRoadsToggle = false;

btn_choose_station_1.Enabled = true;

btn_choose_station_2.Enabled = true;

station1Point.X = e.X;

station1Point.Y = e.Y;

}

else if (chooseStation2Toggle == true)

{

chooseStation1Toggle = false;

chooseStation2Toggle = false;

editRoadsToggle = false;

btn_choose_station_1.Enabled = true;

btn_choose_station_2.Enabled = true;

station2Point.X = e.X;

station2Point.Y = e.Y;

}

else if (editRoadsToggle == true)

{

chooseStation1Toggle = false;

chooseStation2Toggle = false;

editRoadsToggle = false;

btn_choose_station_1.Enabled = true;

btn_choose_station_2.Enabled = true;

}

}

private void btn_choose_station_2_Click(object sender, EventArgs e)

{

chooseStation2Toggle = true;

chooseStation1Toggle = false;

editRoadsToggle = false;

btn_choose_station_1.Enabled = false;

}

private void FormSolution_Load(object sender, EventArgs e)

{

}

private void pb_Click(object sender, EventArgs e)

{

}

private void button1_Click(object sender, EventArgs e)

{

editRoadsToggle = true;

chooseStation1Toggle = false;

chooseStation2Toggle = false;

}

private void btn_calculate_Click(object sender, EventArgs e)

{

calculateAndDrawResult(station1Point, 1);

calculateAndDrawResult(station2Point, 2);

}

private void calculateAndDrawResult(PointF Station, int Key)

{

int Y, X = 0, D, i = 0;

int[,] distanceAndXYArray = new int[3, 802];

if (((downPoint.X == 400) && (downPoint.Y == 200)) || ((downPoint.X == 0) && (downPoint.Y == 200)))

{

for (X = 0; X < 401; X++)

{

Y = lineDrawFormulaY(downPoint, midPoint, X);

D = getLengthOfTwoPoints(new Point(Convert.ToInt32(Station.X), Convert.ToInt32(Station.Y)), new Point(X, Y));

distanceAndXYArray[0, i] = X;

distanceAndXYArray[1, i] = Y;

distanceAndXYArray[2, i] = D;

i++;

}

for (X = 0; X < 401; X++)

{

Y = lineDrawFormulaY(mirrorDownPoint, midPoint, X);

D = getLengthOfTwoPoints(new Point(Convert.ToInt32(Station.X), Convert.ToInt32(Station.Y)), new Point(X, Y));

distanceAndXYArray[0, i] = X;

distanceAndXYArray[1, i] = Y;

distanceAndXYArray[2, i] = D;

i++;

}

}

else

{

for (Y = 0; Y < 401; Y++)

{

X = lineDrawFormulaX(downPoint, midPoint, Y);

D = getLengthOfTwoPoints(new Point(Convert.ToInt32(Station.X), Convert.ToInt32(Station.Y)), new Point(X, Y));

distanceAndXYArray[0, i] = X;

distanceAndXYArray[1, i] = Y;

distanceAndXYArray[2, i] = D;

i++;

}

for (Y = 0; Y < 401; Y++)

{

X = lineDrawFormulaX(mirrorDownPoint, midPoint, Y);

D = getLengthOfTwoPoints(new Point(Convert.ToInt32(Station.X), Convert.ToInt32(Station.Y)), new Point(X, Y));

distanceAndXYArray[0, i] = X;

distanceAndXYArray[1, i] = Y;

distanceAndXYArray[2, i] = D;

i++;

}

}

int minElement = distanceAndXYArray[2, 0];

int minI = 0;

for (i = 0; i < 800; i++)

{

if (minElement > distanceAndXYArray[2, i])

{

minElement = distanceAndXYArray[2, i];

minI = i;

}

}

Graphics g = pb.CreateGraphics();

Rectangle drawRect;

if (Key == 1)

{

minRoadToStation1Point.X = distanceAndXYArray[0, minI];

minRoadToStation1Point.Y = distanceAndXYArray[1, minI];

drawRect = new Rectangle(minRoadToStation1Point.X - 3, minRoadToStation1Point.Y - 3, 6, 6);

g.DrawEllipse(new Pen(Color.Black, 2), drawRect);

g.DrawLine(new Pen(Color.Black, 2), Station, minRoadToStation1Point);

}

else if (Key == 2)

{

minRoadToStation2Point.X = distanceAndXYArray[0, minI];

minRoadToStation2Point.Y = distanceAndXYArray[1, minI];

drawRect = new Rectangle(minRoadToStation2Point.X - 3, minRoadToStation2Point.Y - 3, 6, 6);

g.DrawEllipse(new Pen(Color.Black,2), drawRect);

g.DrawLine(new Pen(Color.Black, 2), Station, minRoadToStation2Point);

}

totalDistance = 0;

totalDistance += getLengthOfTwoPoints(new Point(Convert.ToInt32(station1Point.X), Convert.ToInt32(station1Point.Y)), minRoadToStation1Point);

totalDistance += getLengthOfTwoPoints(new Point(Convert.ToInt32(station2Point.X), Convert.ToInt32(station2Point.Y)), minRoadToStation2Point);

totalDistance += getLengthOfTwoPoints(minRoadToStation1Point, midPoint);

totalDistance += getLengthOfTwoPoints(minRoadToStation2Point, midPoint);

g.DrawString("Расстояние пути: " + Convert.ToString(totalDistance), drawFontArial10, drawBrushBlack, new PointF(50, 20));

}

private int getLengthOfTwoPoints(Point po1, Point po2)

{

return Convert.ToInt32(Math.Sqrt(Math.Pow((po2.X-po1.X),2)+Math.Pow((po2.Y-po1.Y),2)));

}

private void pb_Paint(object sender, PaintEventArgs e)

{

}

}

}