/// <summary> /// Creates the surface for the Acceleration based on speed and distance (A(V,d)) /// </summary> /// <returns></returns> public AccelerationSpeedDistanceSurface createAccelerationSpeedDistanceSurface(double expectedEndX, double expectedEndY) { AccelerationSpeedDistanceSurface retVal = new AccelerationSpeedDistanceSurface(); foreach (Segment segment in Segments) { Graph graph = segment.Graph; FlatAccelerationSpeedCurve acc = graph.FlatAccelerationSpeedCurve(expectedEndY); for (int i = 0; i < acc.SegmentCount; i++) { double start = segment.Start; double end = segment.End; if (end == double.MaxValue) { end = expectedEndX; } ConstantCurveSegment <SiSpeed, SiAcceleration> seg = acc[i]; SurfaceTile tile = new SurfaceTile( new SiDistance(start, SiDistance_SubUnits.Meter), new SiDistance(end, SiDistance_SubUnits.Meter), seg.X.X0, seg.X.X1, seg.Y ); retVal.Tiles.Add(tile); } } return(retVal); }
/// <summary> /// Creates the picture associated to this graph /// </summary> /// <param name="name"></param> /// <returns>the corresponding bitmap</returns> public Bitmap Display() { Bitmap retVal = null; SpeedDistanceCurvePlotter display = new SpeedDistanceCurvePlotter(); String name = null; /// Computes the expected end to display double expectedEndX = 0; Dictionary <Function, Graph> graphs = new Dictionary <Function, Graph>(); foreach (Function function in Functions) { InterpretationContext context = new InterpretationContext(function); if (function.FormalParameters.Count == 1) { Parameter parameter = (Parameter)function.FormalParameters[0]; Graph graph = function.createGraph(context, parameter); if (graph != null) { expectedEndX = Math.Max(expectedEndX, graph.ExpectedEndX()); graphs.Add(function, graph); } } } double expectedEndY = 0; Dictionary <Function, Surface> surfaces = new Dictionary <Function, Surface>(); foreach (Function function in Functions) { InterpretationContext context = new InterpretationContext(function); if (function.FormalParameters.Count == 2) { Surface surface = function.createSurface(context); if (surface != null) { expectedEndX = Math.Max(expectedEndX, surface.ExpectedEndX()); expectedEndY = Math.Max(expectedEndY, surface.ExpectedEndY()); surfaces.Add(function, surface); } } } // Don't display surfaces that are too big if (setMaximumYValueCheckBox.Checked) { try { int maxY = Int32.Parse(maximumYValueTextBox.Text); expectedEndY = Math.Min(expectedEndY, maxY); } catch (Exception) { } } expectedEndY = Math.Min(600, expectedEndY); int i = 0; /// Creates the graphs foreach (KeyValuePair <Function, Graph> pair in graphs) { Function function = pair.Key; Graph graph = pair.Value; if (graph != null) { if (graph.IsFlat()) { FlatSpeedDistanceCurve curve = graph.FlatSpeedDistanceCurve(expectedEndX); display.AddCurve(curve, function.FullName, COLORS[i % COLORS.Length]); } else { QuadraticSpeedDistanceCurve curve = graph.QuadraticSpeedDistanceCurve(expectedEndX); display.AddCurve(curve, function.FullName, COLORS[i % COLORS.Length]); } if (name == null) { name = function.Name; } } i += 1; } /// Creates the surfaces foreach (KeyValuePair <Function, Surface> pair in surfaces) { Function function = pair.Key; Surface surface = pair.Value; if (surface != null) { AccelerationSpeedDistanceSurface curve = surface.createAccelerationSpeedDistanceSurface(expectedEndX, expectedEndY); display.AddCurve(curve, function.FullName); if (name == null) { name = function.Name; } } } if (name != null) { display.GnuPlot_Home_Path = Path.GetDirectoryName(Application.ExecutablePath) + "\\gnuplot\\bin"; string outputDir = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData) + "\\ERTMSFormalSpecs"; System.IO.Directory.CreateDirectory(outputDir); display.Output_Path = outputDir; display.Base_Name = "EFSPicture_" + name; display.ImageWidth = 1200; display.ImageHeight = 600; display.EraseTemporaryFiles = false; display.ShowColouredSegments = false; if (setMinimumValueCheckBox.Checked) { try { double val = double.Parse(minimumValueTextBox.Text); display.Min_X = new SiDistance(val, SiDistance_SubUnits.Meter); } catch (Exception) { } } if (setMaximumValueCheckBox.Checked) { try { double val = double.Parse(maximumValueTextBox.Text); display.Max_X = new SiDistance(val, SiDistance_SubUnits.Meter); } catch (Exception) { } } if (display.Plot()) { // Sometimes, a handle is still open on the corresponding file which forbids opening the stream on it // Wait a bit until the handle is no more open System.IO.FileStream stream = null; System.DateTime start = System.DateTime.Now; while (stream == null && System.DateTime.Now - start < new TimeSpan(0, 0, 5)) { try { stream = new System.IO.FileStream(display.ImageFileName, System.IO.FileMode.Open, System.IO.FileAccess.Read); } catch (Exception) { System.Threading.Thread.Sleep(100); } } if (stream != null) { try { retVal = new Bitmap(stream); } catch (Exception) { } finally { stream.Close(); // System.IO.File.Delete(display.ImageFileName); } } } } return(retVal); }
/// <summary> /// Provides the graph of this function if it has been statically defined /// </summary> /// <param name="context">the context used to create the graph</param> /// <returns></returns> public override Graph createGraph(Interpreter.InterpretationContext context, Parameter parameter) { Graph retVal = null; Graph MRSPGraph = null; Function speedRestriction = context.findOnStack(SpeedRestrictions).Value as Function; if (speedRestriction != null) { Parameter p = (Parameter)speedRestriction.FormalParameters[0]; int token = context.LocalScope.PushContext(); context.LocalScope.setGraphParameter(p); MRSPGraph = createGraphForValue(context, context.findOnStack(SpeedRestrictions).Value, p); context.LocalScope.PopContext(token); } if (MRSPGraph != null) { Function deceleratorFactor = context.findOnStack(DecelerationFactor).Value as Function; if (deceleratorFactor != null) { Surface DecelerationSurface = deceleratorFactor.createSurface(context); if (DecelerationSurface != null) { FlatSpeedDistanceCurve MRSPCurve = MRSPGraph.FlatSpeedDistanceCurve(MRSPGraph.ExpectedEndX()); AccelerationSpeedDistanceSurface accelerationSurface = DecelerationSurface.createAccelerationSpeedDistanceSurface(double.MaxValue, double.MaxValue); QuadraticSpeedDistanceCurve BrakingCurve = null; try { BrakingCurve = EtcsBrakingCurveBuilder.Build_A_Safe_Backward(accelerationSurface, MRSPCurve); } catch (System.Exception e) { retVal = new Graph(); retVal.addSegment(new Graph.Segment(0, double.MaxValue, new Graph.Segment.Curve(0, 0, 0))); } if (BrakingCurve != null) { retVal = new Graph(); // TODO : Remove the distinction between linear curves and quadratic curves bool isLinear = true; for (int i = 0; i < BrakingCurve.SegmentCount; i++) { QuadraticCurveSegment segment = BrakingCurve[i]; if (segment.A.ToUnits() != 0.0 || segment.V0.ToUnits() != 0.0) { isLinear = false; break; } } for (int i = 0; i < BrakingCurve.SegmentCount; i++) { QuadraticCurveSegment segment = BrakingCurve[i]; Graph.Segment newSegment; if (isLinear) { newSegment = new Graph.Segment( segment.X.X0.ToUnits(), segment.X.X1.ToUnits(), new Graph.Segment.Curve(0.0, segment.V0.ToSubUnits(SiSpeed_SubUnits.KiloMeter_per_Hour), 0.0)); } else { newSegment = new Graph.Segment( segment.X.X0.ToUnits(), segment.X.X1.ToUnits(), new Graph.Segment.Curve( segment.A.ToSubUnits(SiAcceleration_SubUnits.Meter_per_SecondSquare), segment.V0.ToSubUnits(SiSpeed_SubUnits.KiloMeter_per_Hour), segment.D0.ToSubUnits(SiDistance_SubUnits.Meter) ) ); } retVal.addSegment(newSegment); } } } else { Log.Error("Cannot create surface for " + DecelerationFactor.ToString()); } } else { Log.Error("Cannot evaluate " + DecelerationFactor.ToString() + " as a function"); } } else { Log.Error("Cannot create graph for " + SpeedRestrictions.ToString()); } return(retVal); }
/// <summary> /// Creates a graph for the function /// </summary> /// <param name="context"></param> /// <param name="parameter"></param> /// <param name="explain"></param> /// <returns></returns> public override Graph CreateGraph(InterpretationContext context, Parameter parameter, ExplanationPart explain) { Graph retVal = new Graph(); StructureValue LocationStruct = context.FindOnStack(Target).Value as StructureValue; SiDistance location; SiSpeed speed; if (LocationStruct != null) { IVariable locationField = LocationStruct.Val["Location"] as IVariable; location = new SiDistance((locationField.Value as DoubleValue).Val); IVariable speedField = LocationStruct.Val["Speed"] as IVariable; speed = new SiSpeed((speedField.Value as DoubleValue).Val, SiSpeed_SubUnits.KiloMeter_per_Hour); Function decelerationFactor = context.FindOnStack(DecelerationFactor).Value as Function; if (decelerationFactor != null) { Surface DecelerationSurface = decelerationFactor.CreateSurface(context, explain); if (DecelerationSurface != null) { AccelerationSpeedDistanceSurface accelerationSurface = DecelerationSurface.createAccelerationSpeedDistanceSurface(double.MaxValue, double.MaxValue); QuadraticSpeedDistanceCurve BrakingCurve = null; try { BrakingCurve = EtcsBrakingCurveBuilder.Build_Deceleration_Curve(accelerationSurface, speed, location); } catch (Exception e) { retVal.AddSegment(new Graph.Segment(0, double.MaxValue, new Graph.Segment.Curve(0, 0, 0))); } SiSpeed finalSpeed = new SiSpeed(GetDoubleValue(context.FindOnStack(EndSpeed).Value), SiSpeed_SubUnits.KiloMeter_per_Hour); for (int i = 0; i < BrakingCurve.SegmentCount; i++) { QuadraticCurveSegment segment = BrakingCurve[i]; SiSpeed endSpeed = Max(finalSpeed, segment.Get(segment.X.X1)); SiDistance endDistance; if (endSpeed == finalSpeed) { // Ensures that a braking curve is calculated until the finalSpeed // but not further than the end of the curve segment SiSpeed tmp = Max(segment.Get(segment.X.X1), endSpeed - new SiSpeed(0.001)); endDistance = segment.IntersectAt(tmp); } else { endDistance = segment.X.X1; } Graph.Segment newSegment = new Graph.Segment( segment.X.X0.ToUnits(), endDistance.ToUnits(), new Graph.Segment.Curve( segment.A.ToSubUnits(SiAcceleration_SubUnits.Meter_per_SecondSquare), segment.V0.ToSubUnits(SiSpeed_SubUnits.KiloMeter_per_Hour), segment.D0.ToSubUnits(SiDistance_SubUnits.Meter) ) ); retVal.AddSegment(newSegment); if (endSpeed == finalSpeed) { break; } } } } } return(retVal); }