Skip to content

Commit 792d23a

Browse files
committed
Add number of axles. Also lowest derail force (wheel load).
1 parent 8773ee5 commit 792d23a

File tree

5 files changed

+78
-14
lines changed

5 files changed

+78
-14
lines changed

Source/Contrib/ContentManager/ContentInfo.cs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -188,14 +188,16 @@ public static string GetText(Content content)
188188
details.AppendFormat("Name:\t{1}{0}", Environment.NewLine, data.Name);
189189
details.AppendFormat("NumEngines:\t{1}{0}", Environment.NewLine, data.NumEngines);
190190
details.AppendFormat("NumCars:\t{1}{0}", Environment.NewLine, data.NumCars);
191+
details.AppendFormat("Axles:\t{1}{0}", Environment.NewLine, data.NumAxles);
191192
details.AppendFormat("MaxSpeed:\t{1}{0}", Environment.NewLine, FormatStrings.FormatSpeedLimit(data.MaxSpeedMps, IsMetric));
192193
details.AppendFormat("Weight:\t{1}{0}", Environment.NewLine, FormatStrings.FormatLargeMass(data.MassKG, IsMetric, IsUK));
193194
details.AppendFormat("Length:\t{1}{0}", Environment.NewLine, FormatStrings.FormatShortDistanceDisplay(data.LengthM, IsMetric));
194195
details.AppendFormat("Power:\t{1}{0}", Environment.NewLine, FormatStrings.FormatPower(data.MaxPowerW, IsMetric, IsImperialBHP, IsImperialBTUpS));
195196
details.AppendFormat("MaxTE:\t{1}{0}", Environment.NewLine, FormatStrings.FormatForce(data.MaxTractiveForceN, IsMetric));
196-
details.AppendFormat("MinCouplerStrength:\t{1}{0}", Environment.NewLine, FormatStrings.FormatForce(data.MinCouplerStrengthN, IsMetric));
197197
if (!IsMetric && !IsUK) { details.AppendFormat("HPT:\t{1}{0}", Environment.NewLine, FormatHPT(data.MaxPowerW, data.MassKG)); }
198198
if (!IsMetric && !IsUK) { details.AppendFormat("TPOB:\t{1}{0}", Environment.NewLine, FormatTPOB(data.MassKG, data.NumOperativeBrakes)); }
199+
details.AppendFormat("MinCouplerStrength:\t{1}{0}", Environment.NewLine, FormatStrings.FormatForce(data.MinCouplerStrengthN, IsMetric));
200+
details.AppendFormat("MinDerailForce:\t{1}{0}", Environment.NewLine, FormatStrings.FormatForce(data.MinDerailForceN, IsMetric));
199201
details.AppendLine();
200202
details.AppendFormat("Car ID:\tDirection:\tWeight:\tName:\t{0}", Environment.NewLine);
201203
foreach (var car in data.Cars)
@@ -210,14 +212,20 @@ public static string GetText(Content content)
210212
details.AppendFormat("Name:\t{1}{0}", Environment.NewLine, data.Name);
211213
details.AppendFormat("Weight:\t{1} ({2}){0}", Environment.NewLine, FormatStrings.FormatMass(data.MassKG, IsMetric), FormatStrings.FormatLargeMass(data.MassKG, IsMetric, IsUK));
212214
details.AppendFormat("Length:\t{1}{0}", Environment.NewLine, FormatStrings.FormatShortDistanceDisplay(data.LengthM, IsMetric));
213-
if (data.Type == CarType.Engine)
215+
if (data.Type != CarType.Engine)
216+
{
217+
details.AppendFormat("Axles:\t{1}{0}", Environment.NewLine, data.NumAllAxles);
218+
}
219+
else
214220
{
221+
details.AppendFormat("Axles:\t{1}+{2}{0}", Environment.NewLine, data.NumDriveAxles, data.NumAllAxles - data.NumDriveAxles);
215222
details.AppendFormat("MaxPowerW:\t{1}{0}", Environment.NewLine, FormatStrings.FormatPower(data.MaxPowerW, IsMetric, IsImperialBHP, IsImperialBTUpS));
216223
details.AppendFormat("MaxForce:\t{1}{0}", Environment.NewLine, FormatStrings.FormatForce(data.MaxForceN, IsMetric));
217224
details.AppendFormat("MaxSpeed:\t{1}{0}", Environment.NewLine, FormatStrings.FormatSpeedLimit(data.MaxSpeedMps, IsMetric));
218225
}
219-
details.AppendFormat("MaxBrakeF:\t{1}{0}", Environment.NewLine, FormatStrings.FormatForce(data.MaxBarkeForceN, IsMetric));
226+
details.AppendFormat("MaxBrakeF:\t{1}{0}", Environment.NewLine, FormatStrings.FormatForce(data.MaxBrakeForceN, IsMetric));
220227
details.AppendFormat("MinCouplerStrength:\t{1}{0}", Environment.NewLine, FormatStrings.FormatForce(data.MinCouplerStrengthN, IsMetric));
228+
details.AppendFormat("MinDerailForce:\t{1}{0}", Environment.NewLine, FormatStrings.FormatForce(data.MinDerailForceN, IsMetric));
221229
details.AppendLine();
222230
details.AppendFormat("Description:\t{0}{0}{1}{0}{0}", Environment.NewLine, data.Description);
223231
}

Source/Contrib/ContentManager/Models/Car.cs

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,16 @@
1515
// You should have received a copy of the GNU General Public License
1616
// along with Open Rails. If not, see <http://www.gnu.org/licenses/>.
1717

18+
// MSTS Wheels and ORTS Axles
19+
// * ORTS uses unpowered and drive axles. Eg. 2 and 4 for an ES44C4
20+
// * MSTS uses a mix of wheels and axle. The Wagon section has the total,
21+
// the Engine section the driven only.
22+
// Values greater than 6 are wheels, less than 6 are axles. Some are
23+
// intentionally wrong to work around MSTS issues.
24+
1825
using Orts.Formats.Msts;
1926
using System;
20-
using System.Collections.Generic;
2127
using System.Diagnostics;
22-
using System.Linq;
23-
using System.Text;
2428

2529
namespace ORTS.ContentManager.Models
2630
{
@@ -38,24 +42,29 @@ public class Car
3842
public readonly string Description;
3943
public readonly float MassKG;
4044
public readonly float LengthM;
41-
public readonly float MaxBarkeForceN;
45+
public readonly int NumDriveAxles;
46+
public readonly int NumAllAxles;
47+
public readonly float MaxBrakeForceN;
4248
public readonly float MaxPowerW;
4349
public readonly float MaxForceN;
4450
public readonly float MaxSpeedMps;
4551
public readonly float MinCouplerStrengthN;
52+
public readonly float MinDerailForceN;
4653

4754
public Car(Content content)
4855
{
4956
Debug.Assert(content.Type == ContentType.Car);
5057

58+
const float GravitationalAccelerationMpS2 = 9.80665f;
59+
5160
// .eng files also have a wagon block
5261
var wagFile = new WagonFile(content.PathName);
5362
Type = CarType.Wagon;
5463
SubType = wagFile.WagonType;
5564
Name = wagFile.Name;
5665
MassKG = wagFile.MassKG;
5766
LengthM = wagFile.WagonSize.LengthM;
58-
MaxBarkeForceN = wagFile.MaxBrakeForceN;
67+
MaxBrakeForceN = wagFile.MaxBrakeForceN;
5968
MinCouplerStrengthN = wagFile.MinCouplerStrengthN;
6069

6170
if (System.IO.Path.GetExtension(content.PathName).Equals(".eng", StringComparison.OrdinalIgnoreCase))
@@ -68,7 +77,23 @@ public Car(Content content)
6877
MaxForceN = engFile.MaxForceN;
6978
MaxSpeedMps = engFile.MaxSpeedMps;
7079
Description = engFile.Description;
80+
// see MSTSLocomotive.Initialize()
81+
if (engFile.NumDriveAxles > 0) { NumDriveAxles = engFile.NumDriveAxles; }
82+
else if (engFile.NumEngWheels >= 7f) { NumDriveAxles = (int)(engFile.NumEngWheels / 2f); }
83+
else if (engFile.NumEngWheels > 0f) { NumDriveAxles = (int)engFile.NumEngWheels; }
84+
else { NumDriveAxles = 4; }
7185
}
86+
87+
// see MSTSWagon.LoadFromWagFile()
88+
if (wagFile.NumWagAxles > 0) { NumAllAxles = wagFile.NumWagAxles + NumDriveAxles; }
89+
else if (wagFile.NumWagWheels >= 7f) { NumAllAxles = (int)(wagFile.NumWagWheels / 2f); }
90+
else if (wagFile.NumWagWheels > 0f) { NumAllAxles = (int)wagFile.NumWagWheels; }
91+
else { NumAllAxles = 4; }
92+
if (NumDriveAxles > NumAllAxles) { NumAllAxles = NumDriveAxles; }
93+
94+
// see TrainCar.UpdateTrainDerailmentRisk()
95+
var numWheels = NumAllAxles * 2;
96+
if (numWheels > 0) { MinDerailForceN = MassKG / numWheels * GravitationalAccelerationMpS2; }
7297
}
7398
}
7499
}

Source/Contrib/ContentManager/Models/Consist.cs

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,6 @@
2020
using System.Collections.Generic;
2121
using System.Diagnostics;
2222
using System.IO;
23-
using System.Linq;
24-
using System.Runtime.CompilerServices;
25-
using System.Text;
2623

2724
namespace ORTS.ContentManager.Models
2825
{
@@ -33,12 +30,14 @@ public class Consist
3330
public readonly string NumCars;
3431
public readonly float MaxSpeedMps;
3532
public readonly float LengthM = 0F;
33+
public readonly int NumAxles = 0;
3634
public readonly float MassKG = 0F;
3735
public readonly float MaxPowerW = 0F;
3836
public readonly float MaxTractiveForceN = 0F;
3937
public readonly float MaxBrakeForce = 0F;
4038
public readonly int NumOperativeBrakes = 0;
4139
public readonly float MinCouplerStrengthN = 9.999e8f; // impossible high force
40+
public readonly float MinDerailForceN = 9.999e8f; // impossible high force
4241

4342
public readonly IEnumerable<Car> Cars;
4443

@@ -60,7 +59,7 @@ public Consist(Content content)
6059
var CarList = new List<Car>();
6160
foreach (Wagon wag in file.Train.TrainCfg.WagonList)
6261
{
63-
float wagonMassKG = 0;
62+
float wagonMassKG = 0; int numEngAxlesOrts = 0;
6463
try
6564
{
6665
var fileType = wag.IsEngine ? ".eng" : ".wag";
@@ -78,15 +77,37 @@ public Consist(Content content)
7877
if (wag.IsEngine && engFile.MaxForceN > 25000) // exclude legacy driving trailers / cab-cars
7978
{
8079
EngCount++;
81-
8280
MaxPowerW += engFile.MaxPowerW;
8381
MaxTractiveForceN += engFile.MaxForceN;
82+
numEngAxlesOrts = engFile.NumDriveAxles;
8483
}
8584
else if (!wag.IsEOT && wagonFile.WagonSize.LengthM > 1.1) // exclude legacy EOT
8685
{
8786
WagCount++;
8887
}
89-
} catch (IOException e) // continue without details when eng/wag file does not exist
88+
89+
int totAxles = 0;
90+
// see MSTSWagon.LoadFromWagFile()
91+
if (numEngAxlesOrts > 0) { totAxles = numEngAxlesOrts + wagonFile.NumWagAxles; }
92+
else if (wagonFile.NumWagAxles > 0) { totAxles = wagonFile.NumWagAxles; }
93+
else if (wagonFile.NumWagWheels >= 7f) { totAxles = (int)(wagonFile.NumWagWheels / 2f); }
94+
else if (wagonFile.NumWagWheels >= 0f) { totAxles = (int)wagonFile.NumWagWheels; }
95+
else { totAxles = 4; }
96+
97+
// exclude legacy EOT from total axle count
98+
if (!wag.IsEOT && wagonFile.WagonSize.LengthM > 1.1)
99+
{
100+
NumAxles += totAxles;
101+
}
102+
103+
if (totAxles > 0 && wagonFile.MassKG > 1000)
104+
{
105+
const float GravitationalAccelerationMpS2 = 9.80665f;
106+
var derailForce = wagonFile.MassKG / totAxles / 2f * GravitationalAccelerationMpS2;
107+
if (derailForce > 1000f) { MinDerailForceN = Math.Min(MinDerailForceN, derailForce); }
108+
}
109+
}
110+
catch (IOException e) // continue without details when eng/wag file does not exist
90111
{
91112
if (wag.IsEngine) { EngCount++; } else { WagCount++; }
92113
}

Source/Orts.Formats.Msts/EngineFile.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,16 @@ public class EngineFile
3232
public float MaxPowerW;
3333
public float MaxForceN;
3434
public float MaxSpeedMps;
35+
public int NumDriveAxles; // ORTS
36+
public float NumEngWheels; // MSTS
3537
public string Description;
3638
public string CabViewFile;
3739

3840
public EngineFile(string filePath)
3941
{
4042
Name = Path.GetFileNameWithoutExtension(filePath);
4143
using (var stf = new STFReader(filePath, false))
44+
{
4245
stf.ParseFile(new STFReader.TokenProcessor[] {
4346
new STFReader.TokenProcessor("engine", ()=>{
4447
stf.ReadString();
@@ -48,11 +51,14 @@ public EngineFile(string filePath)
4851
new STFReader.TokenProcessor("maxpower", ()=>{ MaxPowerW = stf.ReadFloatBlock( STFReader.UNITS.Power, null); }),
4952
new STFReader.TokenProcessor("maxforce", ()=>{ MaxForceN = stf.ReadFloatBlock( STFReader.UNITS.Force, null); }),
5053
new STFReader.TokenProcessor("maxvelocity", ()=>{ MaxSpeedMps = stf.ReadFloatBlock( STFReader.UNITS.Speed, null); }),
54+
new STFReader.TokenProcessor("ortsnumberdriveaxles", ()=>{ NumDriveAxles = stf.ReadIntBlock( 0); }),
55+
new STFReader.TokenProcessor("numwheels", ()=>{ NumEngWheels = stf.ReadFloatBlock( STFReader.UNITS.None, 0f); }),
5156
new STFReader.TokenProcessor("description", ()=>{ Description = stf.ReadStringBlock(null); }),
5257
new STFReader.TokenProcessor("cabview", ()=>{ CabViewFile = stf.ReadStringBlock(null); }),
5358
});
5459
}),
5560
});
61+
}
5662
}
5763

5864
public override string ToString()

Source/Orts.Formats.Msts/WagonFile.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ public class WagonFile
3232
public string WagonType;
3333
public float MassKG;
3434
public CarSize WagonSize;
35+
public int NumWagAxles; // ORTS
36+
public float NumWagWheels; // MSTS
3537
public float MaxBrakeForceN;
3638
public float MinCouplerStrengthN = ImpossiblyHighForceN;
3739

@@ -107,6 +109,8 @@ public WagonFile(string filePath)
107109
new STFReader.TokenProcessor("type", ()=>{ WagonType = stf.ReadStringBlock(null); }),
108110
new STFReader.TokenProcessor("mass", ()=>{ MassKG = stf.ReadFloatBlock(STFReader.UNITS.Mass, null); }),
109111
new STFReader.TokenProcessor("size", ()=>{ WagonSize = new CarSize( stf); }),
112+
new STFReader.TokenProcessor("ortsnumberaxles", ()=>{ NumWagAxles = stf.ReadIntBlock( 0); }),
113+
new STFReader.TokenProcessor("numwheels", ()=>{ NumWagWheels = stf.ReadFloatBlock( STFReader.UNITS.None, 0f); }),
110114
new STFReader.TokenProcessor("maxbrakeforce", ()=>{ MaxBrakeForceN = stf.ReadFloatBlock(STFReader.UNITS.Force, null); }),
111115
new STFReader.TokenProcessor("coupling", ()=>{ new CouplingSpring( ref MinCouplerStrengthN, stf); })
112116
});

0 commit comments

Comments
 (0)