/// <summary>
        ///     Displays the graph
        /// </summary>
        /// <returns></returns>
        public void Display()
        {
            Util.DontNotify(() =>
            {
                GraphVisualiser.Reset();
                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, null);
                        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, null);
                        if (surface != null)
                        {
                            expectedEndX = Math.Max(expectedEndX, surface.ExpectedEndX());
                            expectedEndY = Math.Max(expectedEndY, surface.ExpectedEndY());
                            surfaces.Add(function, surface);
                        }
                    }
                }

                try
                {
                    int maxX = Int32.Parse(Tb_MaxX.Text);
                    expectedEndX = Math.Min(expectedEndX, maxX);
                }
                catch (Exception)
                {
                }

                // Creates the graphs
                foreach (KeyValuePair<Function, Graph> pair in graphs)
                {
                    Function function = pair.Key;
                    Graph graph = pair.Value;

                    if (graph != null)
                    {
                        EfsProfileFunction efsProfileFunction = new EfsProfileFunction(graph);
                        GraphVisualiser.AddGraph(new EfsProfileFunctionGraph(GraphVisualiser, efsProfileFunction,
                            function.FullName));

                        if (name == null)
                        {
                            name = function.Name;
                        }
                    }
                }

                // Creates the surfaces
                foreach (KeyValuePair<Function, Surface> pair in surfaces)
                {
                    Function function = pair.Key;
                    Surface surface = pair.Value;

                    if (surface != null)
                    {
                        EfsSurfaceFunction efsSurfaceFunction = new EfsSurfaceFunction(surface);
                        GraphVisualiser.AddGraph(new EfsSurfaceFunctionGraph(GraphVisualiser, efsSurfaceFunction,
                            function.FullName));
                        if (name == null)
                        {
                            name = function.Name;
                        }
                    }
                }

                if (name != null)
                {
                    try
                    {
                        double val = double.Parse(Tb_MinX.Text);
                        GraphVisualiser.SetMinX(val);
                    }
                    catch (Exception)
                    {
                    }

                    try
                    {
                        double val = double.Parse(Tb_MaxX.Text);
                        GraphVisualiser.SetMaxX(val);
                    }
                    catch (Exception)
                    {
                    }

                    if (Cb_AutoYSize.Checked)
                    {
                        GraphVisualiser.SetMaxY(double.NaN);
                    }
                    else
                    {
                        double height;
                        if (double.TryParse(Tb_MaxY.Text, out height))
                        {
                            GraphVisualiser.SetMaxY(height);
                        }
                        else
                        {
                            GraphVisualiser.SetMaxY(double.NaN);
                        }
                    }
                    GraphVisualiser.DrawGraphs(expectedEndX);
                }
            });
        }
        /// <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;
        }