Search code examples
c#winformszedgraph

Working with zedgraph XDate values to set Major|MinorStep and BaseTic values for x-axis


I am trying to control the value labels for my zedgraph's x-axis. Before, the labels would "fly around" and not really stay put on the axis. They might move left or right on the axis and pop in and out of existence based on the data. Like in the picture below

enter image description here

I first tried to draw the labels myself when I finally found good documentation for the zedgraph library. There I found the [AXIS].Scale options of MajorStep MinorStep and BaseTic. Which if set correctly should cause the labels to stay in place and just change value as the data is added.

The issue I am running into though is that my x-axis scale is in XDate units. Which means I cannot do the simple math I was hoping to. So I have since figured a way that I think I can find the values I need using TimeSpan and DateTime. Below curMaxX and curMinX are XDate values of the current minimum and maximum x-axis values (curMinX should basically be DateTime.Now because this data is realtime)

// Setup
TimeSpan scaleDist = curMaxX.DateTime.Subtract(curMinX.DateTime);
TimeSpan major = new TimeSpan(scaleDist.Ticks / 5);
TimeSpan minor = new TimeSpan(major.Ticks / 5);
TimeSpan baseT = new TimeSpan(curMinX.DateTime.Ticks + major.Ticks);
// Setting the values
myPane.XAxis.Scale.MajorStep = new XDate(new DateTime(major.Ticks));
myPane.XAxis.Scale.MinorStep = new XDate(new DateTime(minor.Ticks));
myPane.XAxis.Scale.BaseTic = new XDate(new DateTime(baseT.Ticks));
// Print statement of the values
SDist: 00:00:10
Major: 00:00:02
Minor: 00:00:00.4000000
BaseT: 735382.07:32:34
BaseTAsDateTime: 5/30/2014 7:32:34 AM
CurMinX:         5/30/2014 7:32:32 AM

Though setting the values as such still does not achieve what I want. With this code my x-axis comes out looking like so

enter image description here

It is somewhat closer to what I am looking for but still off. Only a single major tic is shown, and no minor tics. I am not sure what other ways there might be to specify the values.

For the major and minor step documentation it says

For Date axes, this value is defined in units of Major/MinorUnit.

Which my MajorUnit is minutes and the MinorUnit is seconds, but I pass them a XDate value which specifies both minutes and seconds. Also, setting the values as fractions of a whole (so if I want MajorStep to be 2 seconds I'd set it as (2/60)), causes nothing to show up.

Any ideas/suggestions?


Solution

  • Well, I determined that it was a waste of time to try and use the default zedgraph tics, steps, etc. So I made my own method to do so based on the data currently on the graph.

    enter image description here

    After I posted this I realized trying to figure out the tics was a lost cause so I looked for other ways to do it. I was going to add text beside each point showing its values, but it became very cluttered, then I realized I can just draw the text at the bottom of the graph which is what I wanted all along. I also added a little label on the right showing the current value.

    A little bit o code

    private void setPointLabels()
    {
        // All hail the almighty pane.
        GraphPane myPane = theGraph.GraphPane;
    
        // Give us some room to draw labels
        myPane.Margin.Right = 50;
        myPane.Margin.Bottom = 20;
    
        // Dont show the default stuff
        myPane.XAxis.Scale.IsVisible = false;
        myPane.XAxis.MajorTic.IsAllTics = false;
        myPane.XAxis.MinorTic.IsAllTics = false;
    
        // Remove the old labels 
        myPane.GraphObjList.Clear();
    
        // Get the curve showing our data
        LineItem myCurve = (LineItem)myPane.CurveList[0];
    
        // Show a voltage value on the far right
    
        PointPair pt = myCurve.Points[myCurve.Points.Count - 1];
        TextObj text = new TextObj(" " + pt.Y.ToString("f2"), pt.X, pt.Y, CoordType.AxisXYScale, AlignH.Left, AlignV.Center);
        text.ZOrder = ZOrder.A_InFront;
        text.FontSpec.Border.IsVisible = false;
        text.FontSpec.Fill.IsVisible = false;
        myPane.GraphObjList.Add(text);
    
        // Determine a hardcoded yOffset for the labels
        double yOffset = -1.2;
    
        // Determine if we need to fix the center label
        int fixVal = 1;
        if (xScaleSec == 10)
            fixVal = 0;
    
        // Loop over each point in the curve
        for (int i = 0; i < myCurve.Points.Count; i++)
        {
            if (i == 0 ||
                i == (myCurve.Points.Count/4) ||
                i == ((myCurve.Points.Count/2)-fixVal) ||
                i == ((3*myCurve.Points.Count)/4) ||
                i == myCurve.Points.Count-1)
            {
                PointPair aPt = myCurve.Points[i];
    
                // Add a text object just below the x-axis showing the point's x-value
                XDate xVal = new XDate(aPt.X);
                TextObj label = new TextObj(xVal.ToString("hh:mm.ss"), aPt.X, myPane.YAxis.Scale.Min + yOffset, CoordType.AxisXYScale, AlignH.Center, AlignV.Center);
                label.ZOrder = ZOrder.A_InFront;
                label.FontSpec.Fill.IsVisible = false;
                label.FontSpec.Border.IsVisible = false;
                myPane.GraphObjList.Add(label);
    
                // Add a line object on the x-axis representing a tic mark
                LineObj aTic = new LineObj(aPt.X, myPane.YAxis.Scale.Min - (yOffset / 4), aPt.X, myPane.YAxis.Scale.Min + (yOffset / 4));
                myPane.GraphObjList.Add(aTic);
            }
        }
    }