Unable to draw a vertical line in ZedGraph

74 Views Asked by At

The following source code is supposed to draw a vertical line using the ZedGraph library.

AddVerticalLine() function is supposed to be able to handle both linear scale and log scale.

However, for some reason it is unable to draw the line, and I am seeing a blank graph pane.

What am I doing incorrectly?

enter image description here

class Program
{
    static void Main(string[] args)
    {
        DataPlotter plotter = new DataPlotter();
        plotter.IsLogX = true;
        plotter.IsLogY = true;
        
        plotter.AddVerticalLine("Vertical Line at 10^2.2", 2.2);
        plotter.ShowDialog();
    }
}
using ZedGraph;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.IO;
using System.Windows.Forms;

public class DataPlotter
{
    private GraphPane myPane_;
    private int curveCounter_ = 0;

    #region [Single line properties]
    public ZedGraphControl ZedGraphCtrl { get; set; }
    public SymbolType DefaultSymbolType { get; set; } = SymbolType.Circle;
    public float DefaultSymbolSize { get; set; } = 7;
    public Color DefaultLineColor { get; set; } = Color.Blue;

    public DashStyle DefaultLineDashStyle { get; set; } = DashStyle.Solid;
    public float DefaultLineWidth { get; set; } = 1;

    public Color? CurveColor { get; set; }
    public SymbolType? CurveSymbolType { get; set; }
    public float? CurveSymbolSize { get; set; }
    public DashStyle? CurveDashStyle { get; set; }
    #endregion

    #region [Multi-line properties]
    public string ImageTitle
    {
        get => myPane_.Title.Text;
        set => myPane_.Title.Text = value;
    }

    public string XAxisTitle
    {
        get => myPane_.XAxis.Title.Text;
        set => myPane_.XAxis.Title.Text = value;
    }

    public string YAxisTitle
    {
        get => myPane_.YAxis.Title.Text;
        set => myPane_.YAxis.Title.Text = value;
    }

    public int Width
    {
        get => ZedGraphCtrl.Width;
        set => ZedGraphCtrl.Width = value;
    }

    public int Height
    {
        get => ZedGraphCtrl.Height;
        set => ZedGraphCtrl.Height = value;
    }

    public bool IsLogX
    {
        get => myPane_.XAxis.Type == AxisType.Log;
        set => myPane_.XAxis.Type = value ? AxisType.Log : AxisType.Linear;
    }

    public bool IsLogY
    {
        get => myPane_.YAxis.Type == AxisType.Log;
        set => myPane_.YAxis.Type = value ? AxisType.Log : AxisType.Linear;
    }

    private bool _isSymbolVisible = true;

    public bool IsSymbolVisible
    {
        get => _isSymbolVisible;
        set
        {
            _isSymbolVisible = value;
            foreach (CurveItem curve in myPane_.CurveList)
            {
                if (curve is LineItem lineItem)
                {
                    lineItem.Symbol.IsVisible = value;
                }
            }
            ZedGraphCtrl.Invalidate();
        }
    }

    public bool IsLegendVisible
    {
        get => myPane_.Legend.IsVisible;
        set
        {
            myPane_.Legend.IsVisible = value;
            ZedGraphCtrl.Invalidate();
        }
    }
    #endregion

    #region [ctor]
    public DataPlotter()
    {
        ZedGraphCtrl = new ZedGraphControl();
        ZedGraphCtrl.Size = GetDisplayScreenResolution();
        myPane_ = ZedGraphCtrl.GraphPane;

        ImageTitle = "Image Title";
        XAxisTitle = "X Axis";
        YAxisTitle = "Y Axis";
        IsLogX = false;
        IsLogY = false;
        IsLegendVisible = true;
        IsSymbolVisible = false;
        ZedGraphCtrl.Dock = System.Windows.Forms.DockStyle.Fill;
    }
    #endregion



    // Method to bring the specified curve to the front
    private void BringCurveToFront(LineItem curve)
    {
        myPane_.CurveList.Remove(curve);
        myPane_.CurveList.Insert(0, curve);
        ZedGraphCtrl.Invalidate();
    }

    public void SavePlot(string outputPath, string outputFileName)
    {
        try
        {
            if (!Directory.Exists(outputPath))
            {
                Directory.CreateDirectory(outputPath);
            }

            string fullPath = Path.Combine(outputPath, outputFileName);

            ZedGraphCtrl.AxisChange();
            ZedGraphCtrl.Invalidate();

            using (Bitmap bmp = new Bitmap(ZedGraphCtrl.Width, ZedGraphCtrl.Height))
            {
                ZedGraphCtrl.DrawToBitmap(bmp, new Rectangle(0, 0, ZedGraphCtrl.Width, ZedGraphCtrl.Height));
                bmp.Save(fullPath, ImageFormat.Png);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("An error occurred while saving the plot: " + ex.Message);
        }
    }

    private Size GetDisplayScreenResolution()
    {
        // PrimaryScreen represents the primary display monitor
        Rectangle resolution = Screen.PrimaryScreen.Bounds;

        // Create a Size structure to hold the width and height of the primary screen
        Size screenSize = new Size(resolution.Width, resolution.Height);

        return screenSize;
    }

    public void Clear()
    {
        myPane_.CurveList.Clear();
        ZedGraphCtrl.Invalidate();
    }

    public void ShowDialog()
    {
        DataPlotterForm f = new DataPlotterForm();
        ZedGraphCtrl.Dock = DockStyle.Fill;
        f.Controls.Add(ZedGraphCtrl);
        f.WindowState = FormWindowState.Maximized;
        f.ShowDialog();
    }


    #region [AddVerticalLine]
    public void AddVerticalLine(string curveName, double xValue, Color? curveColor = null)
    {
        Color actualCurveColor = curveColor ?? DefaultLineColor;

        if (IsLogX)
        {
            xValue = Math.Pow(10, xValue);
        }

        PointPairList list = new PointPairList();
        double minY = myPane_.YAxis.Scale.Min;
        double maxY = myPane_.YAxis.Scale.Max;

        if (myPane_.YAxis.Type == AxisType.Log)
        {
            minY = Math.Max(minY, 1.0); 
            maxY = Math.Max(maxY, minY * 10); 
        }

        list.Add(xValue, minY); 
        list.Add(xValue, maxY); 

        LineItem myCurve = myPane_.AddCurve(curveName, list, actualCurveColor, SymbolType.None);

        myCurve.Line.IsVisible = true;
        myCurve.Line.Style = DashStyle.Solid;
        myCurve.Line.Width = 2.0F;

        myCurve.Symbol.IsVisible = false;

        ZedGraphCtrl.Invalidate();
    }
    #endregion
}
2

There are 2 best solutions below

0
Matteo Umili On BEST ANSWER

As suggested by @dlr the line is being plotted, you just can't see it because your XScale is not set (so it defaults from 0.0 to 1.2) and your line is being plotted in X=10^2.2.

You can modify AddVerticalLine method like this:

public void AddVerticalLine(string curveName, double xValue, Color? curveColor = null)
{
    Color actualCurveColor = curveColor ?? DefaultLineColor;

    if (IsLogX)
    {
        xValue = Math.Pow(10, xValue);
    }
    // IsLogX is true, so xValue becomes 10^2.2 (~158.49)
    // But your XAxis is being displayed from 0.0 to 1.0
    // So the line is plotted correctly, it's just out of scale
    // To fix we just change the scale of the graph
    myPane_.XAxis.Scale.Min = xValue - 10.0d;
    myPane_.XAxis.Scale.Max = xValue + 10.0d;
    ////////////////////////////////////////////////////


    PointPairList list = new PointPairList();
    double minY = myPane_.YAxis.Scale.Min;
    double maxY = myPane_.YAxis.Scale.Max;

    if (myPane_.YAxis.Type == AxisType.Log)
    {
        minY = Math.Max(minY, 1.0);
        maxY = Math.Max(maxY, minY * 100);
    }


    list.Add(xValue, minY);
    list.Add(xValue, maxY);

    LineItem myCurve = myPane_.AddCurve(curveName, list, actualCurveColor, SymbolType.None);

    myCurve.Line.IsVisible = true;
    myCurve.Line.Style = DashStyle.Solid;
    myCurve.Line.Width = 2.0F;

    myCurve.Symbol.IsVisible = false;

    ZedGraphCtrl.Invalidate();
}
0
dlr On

I suspect that the line may be off the graph. I only see the scale setting at the origin. I use vertical lines in some apps, substituted your code (AddVerticalLine method only) with minor modifications (no change in function). Your code works. Try using the scroll wheel to zoom out to see if you can find where the lines are placed. If that doesn't work, then it may be that you must first load a curve of some sort other than vertical lines only. My code always loads one or more curves, then the ZedGraph axis change adjusts the scales. Only then do I add a vertical line.