internal static void UpdateTrains(double TimeElapsed)
{
for (int i = 0; i < Trains.Length; i++) {
UpdateTrain(Trains[i], TimeElapsed);
}
// detect collision
if (!Game.MinimalisticSimulation & Interface.CurrentOptions.Collisions)
{
//for (int i = 0; i < Trains.Length; i++) {
System.Threading.Tasks.Parallel.For(0, Trains.Length, i =>
{
// with other trains
if (Trains[i].State == TrainState.Available)
{
double a = Trains[i].Cars[0].FrontAxle.Follower.TrackPosition - Trains[i].Cars[0].FrontAxlePosition +
0.5*Trains[i].Cars[0].Length;
double b = Trains[i].Cars[Trains[i].Cars.Length - 1].RearAxle.Follower.TrackPosition -
Trains[i].Cars[Trains[i].Cars.Length - 1].RearAxlePosition - 0.5*Trains[i].Cars[0].Length;
for (int j = i + 1; j < Trains.Length; j++)
{
if (Trains[j].State == TrainState.Available)
{
double c = Trains[j].Cars[0].FrontAxle.Follower.TrackPosition -
Trains[j].Cars[0].FrontAxlePosition + 0.5*Trains[j].Cars[0].Length;
double d = Trains[j].Cars[Trains[j].Cars.Length - 1].RearAxle.Follower.TrackPosition -
Trains[j].Cars[Trains[j].Cars.Length - 1].RearAxlePosition -
0.5*Trains[j].Cars[0].Length;
if (a > d & b < c)
{
if (a > c)
{
// i > j
int k = Trains[i].Cars.Length - 1;
if (Trains[i].Cars[k].Specs.CurrentSpeed < Trains[j].Cars[0].Specs.CurrentSpeed)
{
double v = Trains[j].Cars[0].Specs.CurrentSpeed -
Trains[i].Cars[k].Specs.CurrentSpeed;
double s = (Trains[i].Cars[k].Specs.CurrentSpeed*Trains[i].Cars[k].Specs.MassCurrent +
Trains[j].Cars[0].Specs.CurrentSpeed*Trains[j].Cars[0].Specs.MassCurrent)/
(Trains[i].Cars[k].Specs.MassCurrent + Trains[j].Cars[0].Specs.MassCurrent);
Trains[i].Cars[k].Specs.CurrentSpeed = s;
Trains[j].Cars[0].Specs.CurrentSpeed = s;
double e = 0.5*(c - b) + 0.0001;
TrackManager.UpdateTrackFollower(ref Trains[i].Cars[k].FrontAxle.Follower,Trains[i].Cars[k].FrontAxle.Follower.TrackPosition + e, false, false);
TrackManager.UpdateTrackFollower(ref Trains[i].Cars[k].RearAxle.Follower,Trains[i].Cars[k].RearAxle.Follower.TrackPosition + e, false, false);
TrackManager.UpdateTrackFollower(ref Trains[j].Cars[0].FrontAxle.Follower,Trains[j].Cars[0].FrontAxle.Follower.TrackPosition - e, false, false);
TrackManager.UpdateTrackFollower(ref Trains[j].Cars[0].RearAxle.Follower,Trains[j].Cars[0].RearAxle.Follower.TrackPosition - e, false, false);
if (Interface.CurrentOptions.Derailments)
{
double f = 2.0/
(Trains[i].Cars[k].Specs.MassCurrent +
Trains[j].Cars[0].Specs.MassCurrent);
double fi = Trains[j].Cars[0].Specs.MassCurrent*f;
double fj = Trains[i].Cars[k].Specs.MassCurrent*f;
double vi = v*fi;
double vj = v*fj;
if (vi > Game.CriticalCollisionSpeedDifference)
Trains[i].Derail(k, TimeElapsed);
if (vj > Game.CriticalCollisionSpeedDifference)
Trains[j].Derail(i, TimeElapsed);
}
// adjust cars for train i
for (int h = Trains[i].Cars.Length - 2; h >= 0; h--)
{
a = Trains[i].Cars[h + 1].FrontAxle.Follower.TrackPosition -
Trains[i].Cars[h + 1].FrontAxlePosition + 0.5*Trains[i].Cars[h + 1].Length;
b = Trains[i].Cars[h].RearAxle.Follower.TrackPosition -
Trains[i].Cars[h].RearAxlePosition - 0.5*Trains[i].Cars[h].Length;
d = b - a - Trains[i].Couplers[h].MinimumDistanceBetweenCars;
if (d < 0.0)
{
d -= 0.0001;
TrackManager.UpdateTrackFollower(ref Trains[i].Cars[h].FrontAxle.Follower,Trains[i].Cars[h].FrontAxle.Follower.TrackPosition - d, false, false);
TrackManager.UpdateTrackFollower(ref Trains[i].Cars[h].RearAxle.Follower,Trains[i].Cars[h].RearAxle.Follower.TrackPosition - d, false, false);
if (Interface.CurrentOptions.Derailments)
{
double f = 2.0/
(Trains[i].Cars[h + 1].Specs.MassCurrent +
Trains[i].Cars[h].Specs.MassCurrent);
double fi = Trains[i].Cars[h + 1].Specs.MassCurrent*f;
double fj = Trains[i].Cars[h].Specs.MassCurrent*f;
double vi = v*fi;
double vj = v*fj;
if (vi > Game.CriticalCollisionSpeedDifference)
Trains[i].Derail(h + 1, TimeElapsed);
if (vj > Game.CriticalCollisionSpeedDifference)
Trains[i].Derail(h, TimeElapsed);
}
Trains[i].Cars[h].Specs.CurrentSpeed =
Trains[i].Cars[h + 1].Specs.CurrentSpeed;
}
}
// adjust cars for train j
for (int h = 1; h < Trains[j].Cars.Length; h++)
{
a = Trains[j].Cars[h - 1].RearAxle.Follower.TrackPosition -
Trains[j].Cars[h - 1].RearAxlePosition - 0.5*Trains[j].Cars[h - 1].Length;
b = Trains[j].Cars[h].FrontAxle.Follower.TrackPosition -
Trains[j].Cars[h].FrontAxlePosition + 0.5*Trains[j].Cars[h].Length;
d = a - b - Trains[j].Couplers[h - 1].MinimumDistanceBetweenCars;
if (d < 0.0)
{
d -= 0.0001;
TrackManager.UpdateTrackFollower(ref Trains[j].Cars[h].FrontAxle.Follower,Trains[j].Cars[h].FrontAxle.Follower.TrackPosition + d, false, false);
TrackManager.UpdateTrackFollower(ref Trains[j].Cars[h].RearAxle.Follower,Trains[j].Cars[h].RearAxle.Follower.TrackPosition + d, false, false);
if (Interface.CurrentOptions.Derailments)
{
double f = 2.0/
(Trains[j].Cars[h - 1].Specs.MassCurrent +
Trains[j].Cars[h].Specs.MassCurrent);
double fi = Trains[j].Cars[h - 1].Specs.MassCurrent*f;
double fj = Trains[j].Cars[h].Specs.MassCurrent*f;
double vi = v*fi;
double vj = v*fj;
if (vi > Game.CriticalCollisionSpeedDifference)
Trains[j].Derail(h -1, TimeElapsed);
if (vj > Game.CriticalCollisionSpeedDifference)
Trains[j].Derail(h, TimeElapsed);
}
Trains[j].Cars[h].Specs.CurrentSpeed =
Trains[j].Cars[h - 1].Specs.CurrentSpeed;
}
}
}
}
else
{
// i < j
int k = Trains[j].Cars.Length - 1;
if (Trains[i].Cars[0].Specs.CurrentSpeed > Trains[j].Cars[k].Specs.CurrentSpeed)
{
double v = Trains[i].Cars[0].Specs.CurrentSpeed -
Trains[j].Cars[k].Specs.CurrentSpeed;
double s = (Trains[i].Cars[0].Specs.CurrentSpeed*Trains[i].Cars[0].Specs.MassCurrent +
Trains[j].Cars[k].Specs.CurrentSpeed*Trains[j].Cars[k].Specs.MassCurrent)/
(Trains[i].Cars[0].Specs.MassCurrent + Trains[j].Cars[k].Specs.MassCurrent);
Trains[i].Cars[0].Specs.CurrentSpeed = s;
Trains[j].Cars[k].Specs.CurrentSpeed = s;
double e = 0.5*(a - d) + 0.0001;
TrackManager.UpdateTrackFollower(ref Trains[i].Cars[0].FrontAxle.Follower,Trains[i].Cars[0].FrontAxle.Follower.TrackPosition - e, false, false);
TrackManager.UpdateTrackFollower(ref Trains[i].Cars[0].RearAxle.Follower,Trains[i].Cars[0].RearAxle.Follower.TrackPosition - e, false, false);
TrackManager.UpdateTrackFollower(ref Trains[j].Cars[k].FrontAxle.Follower,Trains[j].Cars[k].FrontAxle.Follower.TrackPosition + e, false, false);
TrackManager.UpdateTrackFollower(ref Trains[j].Cars[k].RearAxle.Follower,Trains[j].Cars[k].RearAxle.Follower.TrackPosition + e, false, false);
if (Interface.CurrentOptions.Derailments)
{
double f = 2.0/
(Trains[i].Cars[0].Specs.MassCurrent +
Trains[j].Cars[k].Specs.MassCurrent);
double fi = Trains[j].Cars[k].Specs.MassCurrent*f;
double fj = Trains[i].Cars[0].Specs.MassCurrent*f;
double vi = v*fi;
double vj = v*fj;
if (vi > Game.CriticalCollisionSpeedDifference)
Trains[i].Derail(0, TimeElapsed);
if (vj > Game.CriticalCollisionSpeedDifference)
Trains[j].Derail(k, TimeElapsed);
}
// adjust cars for train i
for (int h = 1; h < Trains[i].Cars.Length; h++)
{
a = Trains[i].Cars[h - 1].RearAxle.Follower.TrackPosition -
Trains[i].Cars[h - 1].RearAxlePosition - 0.5*Trains[i].Cars[h - 1].Length;
b = Trains[i].Cars[h].FrontAxle.Follower.TrackPosition -
Trains[i].Cars[h].FrontAxlePosition + 0.5*Trains[i].Cars[h].Length;
d = a - b - Trains[i].Couplers[h - 1].MinimumDistanceBetweenCars;
if (d < 0.0)
{
d -= 0.0001;
TrackManager.UpdateTrackFollower(ref Trains[i].Cars[h].FrontAxle.Follower,Trains[i].Cars[h].FrontAxle.Follower.TrackPosition + d, false, false);
TrackManager.UpdateTrackFollower(ref Trains[i].Cars[h].RearAxle.Follower,Trains[i].Cars[h].RearAxle.Follower.TrackPosition + d, false, false);
if (Interface.CurrentOptions.Derailments)
{
double f = 2.0/
(Trains[i].Cars[h - 1].Specs.MassCurrent +
Trains[i].Cars[h].Specs.MassCurrent);
double fi = Trains[i].Cars[h - 1].Specs.MassCurrent*f;
double fj = Trains[i].Cars[h].Specs.MassCurrent*f;
double vi = v*fi;
double vj = v*fj;
if (vi > Game.CriticalCollisionSpeedDifference)
Trains[i].Derail(h -1, TimeElapsed);
if (vj > Game.CriticalCollisionSpeedDifference)
Trains[i].Derail(h, TimeElapsed);
}
Trains[i].Cars[h].Specs.CurrentSpeed =
Trains[i].Cars[h - 1].Specs.CurrentSpeed;
}
}
// adjust cars for train j
for (int h = Trains[j].Cars.Length - 2; h >= 0; h--)
{
a = Trains[j].Cars[h + 1].FrontAxle.Follower.TrackPosition -
Trains[j].Cars[h + 1].FrontAxlePosition + 0.5*Trains[j].Cars[h + 1].Length;
b = Trains[j].Cars[h].RearAxle.Follower.TrackPosition -
Trains[j].Cars[h].RearAxlePosition - 0.5*Trains[j].Cars[h].Length;
d = b - a - Trains[j].Couplers[h].MinimumDistanceBetweenCars;
if (d < 0.0)
{
d -= 0.0001;
TrackManager.UpdateTrackFollower(ref Trains[j].Cars[h].FrontAxle.Follower,Trains[j].Cars[h].FrontAxle.Follower.TrackPosition - d, false, false);
TrackManager.UpdateTrackFollower(ref Trains[j].Cars[h].RearAxle.Follower,Trains[j].Cars[h].RearAxle.Follower.TrackPosition - d, false, false);
if (Interface.CurrentOptions.Derailments)
{
double f = 2.0/
(Trains[j].Cars[h + 1].Specs.MassCurrent +
Trains[j].Cars[h].Specs.MassCurrent);
double fi = Trains[j].Cars[h + 1].Specs.MassCurrent*f;
double fj = Trains[j].Cars[h].Specs.MassCurrent*f;
double vi = v*fi;
double vj = v*fj;
if (vi > Game.CriticalCollisionSpeedDifference)
Trains[j].Derail(h + 1, TimeElapsed);
if (vj > Game.CriticalCollisionSpeedDifference)
Trains[j].Derail(h, TimeElapsed);
}
Trains[j].Cars[h].Specs.CurrentSpeed =
Trains[j].Cars[h + 1].Specs.CurrentSpeed;
}
}
}
}
}
}
}
}
// with buffers
if (i == PlayerTrain.TrainIndex)
{
double a = Trains[i].Cars[0].FrontAxle.Follower.TrackPosition - Trains[i].Cars[0].FrontAxlePosition +
0.5*Trains[i].Cars[0].Length;
double b = Trains[i].Cars[Trains[i].Cars.Length - 1].RearAxle.Follower.TrackPosition -
Trains[i].Cars[Trains[i].Cars.Length - 1].RearAxlePosition - 0.5*Trains[i].Cars[0].Length;
for (int j = 0; j < Game.BufferTrackPositions.Length; j++)
{
if (a > Game.BufferTrackPositions[j] & b < Game.BufferTrackPositions[j])
{
a += 0.0001;
b -= 0.0001;
double da = a - Game.BufferTrackPositions[j];
double db = Game.BufferTrackPositions[j] - b;
if (da < db)
{
// front
TrackManager.UpdateCarFollowers(ref Trains[i].Cars[0], -da, false, false);
if (Interface.CurrentOptions.Derailments &&
Math.Abs(Trains[i].Cars[0].Specs.CurrentSpeed) > Game.CriticalCollisionSpeedDifference)
{
Trains[i].Derail(0, TimeElapsed);
}
Trains[i].Cars[0].Specs.CurrentSpeed = 0.0;
for (int h = 1; h < Trains[i].Cars.Length; h++)
{
a = Trains[i].Cars[h - 1].RearAxle.Follower.TrackPosition -
Trains[i].Cars[h - 1].RearAxlePosition - 0.5*Trains[i].Cars[h - 1].Length;
b = Trains[i].Cars[h].FrontAxle.Follower.TrackPosition -
Trains[i].Cars[h].FrontAxlePosition + 0.5*Trains[i].Cars[h].Length;
double d = a - b - Trains[i].Couplers[h - 1].MinimumDistanceBetweenCars;
if (d < 0.0)
{
d -= 0.0001;
TrackManager.UpdateCarFollowers(ref Trains[i].Cars[h], d, false, false);
if (Interface.CurrentOptions.Derailments &&
Math.Abs(Trains[i].Cars[h].Specs.CurrentSpeed) >
Game.CriticalCollisionSpeedDifference)
{
Trains[i].Derail(h, TimeElapsed);
}
Trains[i].Cars[h].Specs.CurrentSpeed = 0.0;
}
}
}
else
{
// rear
int c = Trains[i].Cars.Length - 1;
TrackManager.UpdateCarFollowers(ref Trains[i].Cars[c], db, false, false);
if (Interface.CurrentOptions.Derailments &&
Math.Abs(Trains[i].Cars[c].Specs.CurrentSpeed) > Game.CriticalCollisionSpeedDifference)
{
Trains[i].Derail(c, TimeElapsed);
}
Trains[i].Cars[c].Specs.CurrentSpeed = 0.0;
for (int h = Trains[i].Cars.Length - 2; h >= 0; h--)
{
a = Trains[i].Cars[h + 1].FrontAxle.Follower.TrackPosition -
Trains[i].Cars[h + 1].FrontAxlePosition + 0.5*Trains[i].Cars[h + 1].Length;
b = Trains[i].Cars[h].RearAxle.Follower.TrackPosition -
Trains[i].Cars[h].RearAxlePosition - 0.5*Trains[i].Cars[h].Length;
double d = b - a - Trains[i].Couplers[h].MinimumDistanceBetweenCars;
if (d < 0.0)
{
d -= 0.0001;
TrackManager.UpdateCarFollowers(ref Trains[i].Cars[h], -d, false, false);
if (Interface.CurrentOptions.Derailments &&
Math.Abs(Trains[i].Cars[h].Specs.CurrentSpeed) >
Game.CriticalCollisionSpeedDifference)
{
Trains[i].Derail(h, TimeElapsed);
}
Trains[i].Cars[h].Specs.CurrentSpeed = 0.0;
}
}
}
}
}
}
});
}
// compute final angles and positions
//for (int i = 0; i < Trains.Length; i++) {
System.Threading.Tasks.Parallel.For(0, Trains.Length, i =>
{
if (Trains[i].State != TrainState.Disposed & Trains[i].State != TrainManager.TrainState.Bogus)
{
for (int j = 0; j < Trains[i].Cars.Length; j++)
{
Trains[i].Cars[j].FrontAxle.Follower.UpdateWorldCoordinates(true);
Trains[i].Cars[j].FrontBogie.FrontAxle.Follower.UpdateWorldCoordinates(true);
Trains[i].Cars[j].FrontBogie.RearAxle.Follower.UpdateWorldCoordinates(true);
Trains[i].Cars[j].RearAxle.Follower.UpdateWorldCoordinates(true);
Trains[i].Cars[j].RearBogie.FrontAxle.Follower.UpdateWorldCoordinates(true);
Trains[i].Cars[j].RearBogie.RearAxle.Follower.UpdateWorldCoordinates(true);
UpdateTopplingCantAndSpring(Trains[i], j, TimeElapsed);
UpdateBogieTopplingCantAndSpring(Trains[i], j, TimeElapsed);
}
}
});
}