@@ -261,6 +261,9 @@ public class MSTSSteamLocomotive : MSTSLocomotive
261261 float MSTSBoilerLengthM;
262262 float ORBoilerLengthM;
263263 float BoilerLengthM;
264+ float BoilerDiameterM;
265+ float BoilerCrownCoverageHeightM;
266+ float BoilerCrownHeightM;
264267 public float GradientBoilerLevelPercent;
265268 public int MSTSNumCylinders = 2; // Number of Cylinders
266269 public float MSTSCylinderStrokeM; // High pressure cylinders
@@ -955,6 +958,9 @@ public override void Parse(string lowercasetoken, STFReader stf)
955958 case "engine(boilervolume": BoilerVolumeFT3 = stf.ReadFloatBlock(STFReader.UNITS.VolumeDefaultFT3, null); break;
956959 case "engine(boilerlength": MSTSBoilerLengthM = stf.ReadFloatBlock(STFReader.UNITS.Distance, null); break;
957960 case "engine(ortsboilerlength": ORBoilerLengthM = stf.ReadFloatBlock(STFReader.UNITS.Distance, null); break;
961+ case "engine(ortsboilerdiameter": BoilerDiameterM = stf.ReadFloatBlock(STFReader.UNITS.Distance, null); break;
962+ case "engine(ortsboilercrownheight": BoilerCrownHeightM = stf.ReadFloatBlock(STFReader.UNITS.Distance, null); break;
963+ case "engine(ortsboilercrowncoverageheight": BoilerCrownCoverageHeightM = stf.ReadFloatBlock(STFReader.UNITS.Distance, null); break;
958964 case "engine(steamgaugeglassheight": MSTSSteamGaugeGlassHeightM = stf.ReadFloatBlock(STFReader.UNITS.Distance, null); break;
959965 case "engine(ortswatergaugeglassheight": ORSteamGaugeGlassHeightM = stf.ReadFloatBlock(STFReader.UNITS.Distance, null); break;
960966 case "engine(maxboilerpressure": MaxBoilerPressurePSI = stf.ReadFloatBlock(STFReader.UNITS.PressureDefaultPSI, null); break;
@@ -1105,6 +1111,8 @@ public override void Copy(MSTSWagon copy)
11051111 BoilerVolumeFT3 = locoCopy.BoilerVolumeFT3;
11061112 MSTSBoilerLengthM = locoCopy.MSTSBoilerLengthM;
11071113 ORBoilerLengthM = locoCopy.ORBoilerLengthM;
1114+ BoilerCrownHeightM = locoCopy.BoilerCrownHeightM;
1115+ BoilerCrownCoverageHeightM = locoCopy.BoilerCrownCoverageHeightM;
11081116 MSTSSteamGaugeGlassHeightM = locoCopy.MSTSSteamGaugeGlassHeightM;
11091117 ORSteamGaugeGlassHeightM = locoCopy.ORSteamGaugeGlassHeightM;
11101118 MaxBoilerPressurePSI = locoCopy.MaxBoilerPressurePSI;
@@ -1520,13 +1528,24 @@ public override void Initialize()
15201528 }
15211529 */
15221530
1531+ if (ORBoilerLengthM > 0 && ORSteamGaugeGlassHeightM > 0 && BoilerDiameterM == 0)
1532+ {
1533+ BoilerDiameterM = 2.0f;
15231534
1524- if (WaterGlassLengthM > 0 && BoilerLengthM > 0 )
1535+ if (Simulator.Settings.VerboseConfigurationMessages)
1536+ {
1537+ Trace.TraceInformation("Boiler diameter set to default = {0}", FormatStrings.FormatDistance(BoilerCrownCoverageHeightM, IsMetric));
1538+ }
1539+ }
1540+
1541+ if (WaterGlassLengthM > 0 && BoilerLengthM > 0 && ORBoilerLengthM > 0 && BoilerCrownHeightM > 0 && BoilerCrownCoverageHeightM >0)
15251542 {
15261543 WaterGlassLevelGradientEnabled = true;
15271544 }
15281545
1529- // Trace.TraceInformation("Boiler Water Level - MSTSLength {0} ORLength {1} MSTSGlass {2} OR Glass {3} Enabled {4}, WaterGlass {5} BoilerLength {6}", MSTSBoilerLengthM, ORBoilerLengthM, MSTSSteamGaugeGlassHeightM, ORSteamGaugeGlassHeightM, WaterGlassLevelGradientEnabled, WaterGlassLengthM, BoilerLengthM);
1546+ Trace.TraceInformation("Boiler - CrownHeight {0} CrownCoverage {1}", BoilerCrownHeightM, BoilerCrownCoverageHeightM);
1547+
1548+ // Trace.TraceInformation("Boiler Water Level - MSTSLength {0} ORLength {1} MSTSGlass {2} OR Glass {3} Enabled {4}, WaterGlass {5} BoilerLength {6}", MSTSBoilerLengthM, ORBoilerLengthM, MSTSSteamGaugeGlassHeightM, ORSteamGaugeGlassHeightM, WaterGlassLevelGradientEnabled, WaterGlassLengthM, BoilerLengthM);
15301549
15311550 float BoilerVolumeCheck = Me2.ToFt2(EvaporationAreaM2) / BoilerVolumeFT3; //Calculate the Boiler Volume Check value.
15321551 if (BoilerVolumeCheck > 15) // If boiler volume is not in ENG file or less then a viable figure (ie high ratio figure), then set to a default value
@@ -7098,6 +7117,56 @@ private void UpdateAuxiliaries(float elapsedClockSeconds, float absSpeedMpS)
70987117
70997118 private void UpdateWaterGauge()
71007119 {
7120+ // Calculate water glass level when on gradient
7121+ if (WaterGlassLevelGradientEnabled)
7122+ {
7123+ var boilerangleRad = Math.Atan(CurrentElevationPercent / 100);
7124+ var waterVariationLevelM = (float)Math.Sin(boilerangleRad) * BoilerLengthM / 2.0f;
7125+
7126+ float glassLevelGradientM = 0;
7127+
7128+ // Downslope - CurrentElevationPercent = +ve, level variation will be -ve
7129+ // Uphill - CurrentElevationPercent = -ve, level variation will be +ve
7130+ // gradient variation due to slope needs to be reversed
7131+
7132+ glassLevelGradientM = waterVariationLevelM * -1.0f;
7133+
7134+ // Assume that reference glass height is 50% of glass
7135+ var maxWaterVariationIN = Me.ToIn(WaterGlassLengthM) / 2.0f;
7136+
7137+ float glasslevelfraction = 0;
7138+ float glasslevelM = 0;
7139+
7140+ // Calculate water level on level gradient
7141+ var referenceLevelFraction = (BoilerCrownCoverageHeightM + BoilerCrownHeightM + BoilerDiameterM / 2.0f)/BoilerDiameterM;
7142+
7143+ // Convert reference point to reading on glass
7144+ if (WaterFraction > referenceLevelFraction)
7145+ {
7146+ glasslevelfraction = WaterFraction - referenceLevelFraction;
7147+
7148+ }
7149+ else if (WaterFraction < referenceLevelFraction)
7150+ {
7151+ glasslevelfraction = -1.0f * referenceLevelFraction - WaterFraction;
7152+ }
7153+
7154+ glasslevelM = glasslevelfraction * BoilerDiameterM;
7155+
7156+
7157+ var totalglassLevelM = glasslevelM + glassLevelGradientM;
7158+
7159+ GradientBoilerLevelPercent = totalglassLevelM * 100;
7160+
7161+ // Trace.TraceInformation("Gradient - Current {0} BoilAng {1} GlassIN {2} Glass% {3}", CurrentElevationPercent, boilerangleRad, glasslevelIN, GradientBoilerLevelPercent);
7162+
7163+ // Trace.TraceInformation("Boiler - refLevel {0} GlassLevel {1} GlassLevelM {2} GradientLevel {3} TotalLevel {4} % {5}", referenceLevelFraction, glasslevelfraction, glasslevelM, glassLevelGradientM, totalglassLevelM, GradientBoilerLevelPercent);
7164+
7165+ }
7166+
7167+
7168+
7169+
71017170 WaterGlassLevelIN = ((WaterFraction - WaterGlassMinLevel) / (WaterGlassMaxLevel - WaterGlassMinLevel)) * WaterGlassLengthIN;
71027171 WaterGlassLevelIN = MathHelper.Clamp(WaterGlassLevelIN, 0, WaterGlassLengthIN);
71037172
@@ -7124,33 +7193,7 @@ private void UpdateWaterGauge()
71247193 BoilerIsPriming = false;
71257194 }
71267195
7127- // Calculate water glass level when on gradient
7128- if (WaterGlassLevelGradientEnabled)
7129- {
7130- var boilerangleRad = Math.Atan(CurrentElevationPercent / 100);
7131- var waterVariationLevelM = (float)Math.Sin(boilerangleRad) * BoilerLengthM / 2.0f;
7132-
7133- // Assume that reference glass height is 50% of glass
7134- var maxWaterVariationIN = Me.ToIn(WaterGlassLengthM) / 2.0f;
71357196
7136- float glasslevelIN = 0;
7137- float glassLevelFraction = 0;
7138-
7139- if (CurrentElevationPercent > 0) // Downslope - -ve water slope
7140- {
7141- glasslevelIN -= Me.ToIn(waterVariationLevelM) * -1.0f;
7142- }
7143- else // up slope - +ve water level
7144- {
7145- glasslevelIN += Me.ToIn(waterVariationLevelM) * -1.0f;
7146- }
7147-
7148- glassLevelFraction = glasslevelIN / maxWaterVariationIN;
7149-
7150- GradientBoilerLevelPercent = glassLevelFraction * 100;
7151-
7152- // Trace.TraceInformation("Gradient - Current {0} BoilAng {1} GlassIN {2} Glass% {3}", CurrentElevationPercent, boilerangleRad, glasslevelIN, GradientBoilerLevelPercent);
7153- }
71547197
71557198
71567199 }
0 commit comments