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 ;
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.