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

  case SpCol of

   1: fa:= aPosit + aVMinHalfStep ;

   2: fa:= aPosit + aVMinStep ;

  end ;

{Пресекается возможность перевала угла за 360*}

  if fa >= pi2 then

   fa:= fa - pi2 ;

{Угол для дальнейшей работы с ним, на его пересечение поезда(начальный или конечный угол светофора)}

if PeremBool = false then

  atp:= Svetofor.aPosit

  else

   atp:= Svetofor.aPositPerem ;

{Проверяется условие пересечения поедом светофора}

  if ((Svetofor = FirstSvetofor) and ((atp >= aPosit) and (fa > atp)) or ((atp < aPosit) and (fa > atp) and (fa < aPosit))) or

     ((Svetofor <> FirstSvetofor) and (atp >= aPosit) and (fa > atp)) then

   bool:= true ;

 if bool = false then

  aPosit:= fa

  else

   if (PeremBool = false) and (Svetofor.StatusColor > 0) then

   begin

{Выполняется если поезд пересек начальный угол светофора(aPosit), причем на разрешающий сигнал светофора}

    SpCol:= Svetofor.StatusColor ;

    aPosit:= fa ;

    PeremBool:= true ;

   end

    else

     if PeremBool then

     begin

{Выполняется если поезд пересек конечный угол светофора(aPositPerem)}

      Svetofor.NextSvetofor.Train:= self ;

      Svetofor.Train:= nil ;

      Svetofor:= Svetofor.NextSvetofor ;

      PeremBool:= false ;

      PereschetSvetofor ;

     end ;

 end ;

Метод procedure XYSet позволяет записать заполнить поля с углом и координатами поезда.

procedure TTrain.XYSet(fa: real) ;

begin

 aPositP:= fa ;

{Определение координат поезда по углу}

 x:=x0 + round(cos(fa)*Radius) ;

 y:=y0 + round(sin(fa)*Radius) ;

end ;

Метод procedure GoImg позволяет прорисовать поезд.

procedure TTrain.GoImg ;

var

 h, w: Byte ;

begin

 with Canvas do

 begin

  Pen.Color:= clBlack ;

  Brush.Color:= TrColor ;

{Фактическая прорисовка поезда виде шара с номером по середине}

  Ellipse(x-CrTrain,y-CrTrain,x+CrTrain,y+CrTrain) ;

  TextOut(x - IndexWPoint,y - IndexHPoint,IntToStr(Index)) ;

 end ;

end ;

Выделение перечня наиболее важных структур данных:

Два класса TSvetofor и TTrain являются равноправно главными. В их реализации был применен двунаправленный список, который позволяет более эффективнее работать с данными структурами, а так же взаимодействие между классами упрощается. Особенно это заметно, когда необходимо удалить поезд или светофор, потому что в это случае нет необходимости делать рутинную работу по переписыванию индексов (как например, если бы реализация происходила через массивы). Каждый класс содержит в себе методы, которые позволяют действия, которые совершенно независимы от позиции и хода в программе. Все угловые переменные содержат угол в радианах.

Построение алгоритма реализации:

При работе программы могут возникнуть 6 событий: действие, выбор координат, перебивка переменных, добавление, сохранение и загрузка.

*  Действие:

Рассмотрим действие всей системы при срабатывание таймера.

procedure TMain.Timer1Timer(Sender: TObject);

begin

{Создана ли дорога(загружена)}

 if NewPoleBool then

 begin

{Действия, который необходимо делать с определенным интервалом(Timer1.Interval)}

  StepSystem ;

  if PoleNavBool then

   LineCel ;

 end ; 

end;

 NewPoleBool – определят, создана карта(true) или нет(false);

PoleNavBool – определяет, включена функция определения координат для добавления(true) или нет(false);

Метод procedure StepSystem – обеспечивает движении объектов;

procedure StepSystem ;

begin

{Определение следующего сигнала светофоров}

 PereschetSvetofor ;

{Определение следующих координат поездов}

 PereschetTrain ;

{Прорисовка чистого холста с дорогой}

 GoNewPoleImg ;

{Прорисовка светофоров}

 GoSvetoforImg ;

{Прорисовка поездов}

 GoTrainImg ;

end ;

*  Выбор координат:

Метод procedure LineCel – обеспечивает визуальный выбор координат для добавления;

procedure LineCel ;

var

 x, y: integer ;

 s: string ;

begin

{Определение угла относительно фактического центра поля}

 aPoleNav:= ArcTan2(yPoleNav - y0, xPoleNav - x0) ;

 if aPoleNav < 0 then

  aPoleNav:= pi2 + aPoleNav ;

{Определение координат по найденному углу, в соответствии с радиусом дороги}

 x:=x0 + round(cos(aPoleNav)*Radius) ;

 y:=y0 + round(sin(aPoleNav)*Radius) ;

{Прорисовка осей визуального выбора координат}

 with PoleCanvas do

 begin

  Pen.Color:= clBlue ;

  MoveTo(x,0) ;

  LineTo(x,VPoleHeight);

  MoveTo(0,y);

  LineTo(VPoleWidth,y);

  Brush.Color:= clWhite ;

  Rectangle(x-3,y-3,x+3,y+3) ;

 end ;

 str(aPoleNav * 180 / pi:3:3,s) ;

{Визуальное изменение угла в StatusBar1}

 Unit1.main.StatusBar1.Panels[4].Text:= ' Угол: ' + s + ' *' ;

end ;

*  Перебивка переменных:

Значение некоторых переменных определяется в зависимости от угловой константы ak, которая определяется как отношение минимального радиуса(CMinR) к фактическому радиусу(Radius).

procedure ConstInitialization ;

begin

 ak:= CMinR / Radius ;                           {Угловая константа}

 aVTrain:= aCTrain * ak * CrTrain ;      {Угол занимаемый поездом}

 aVMinStep:= aCMinStep * ak ;           {Полный шаг поезда}

 aVMinHalfStep:= aVMinStep / 2 ;      {Половина полного шага поезда}

 aVMinSV_SV:= aCMinSV_SV * ak ;     {Минимальный угол между светофорами}

 VLLSvetofor:= Radius - CLLSvetofor ; {Меньший радиус круга(для прорисовки)}

 VRLSvetofor:= Radius + CLRSvetofor ;{Больший радиус круга(для прорисовки)}

end;

*  Добавление светофора:

Метод function AddSvetofor возвращает true, если возможно добавление.

function AddSvetofor(fa: real): boolean ;

var

  i: Byte ;

 fSvetofor,fNewSvetofor: TSvetofor ;

 fTrain: TTrain ;

 atp, afirst: real ;