ZedGraph custom graph
Asked Answered
S

1

6

I want to make wtih ZedGraph following dynamically chart: enter image description here How to make ZedGraph axes reverse and and time axis? Thanks

UPD 1: I have to try with following code:

GraphPane myPane = zg1.GraphPane;
            myPane.YAxis.Type = AxisType.Date;
            myPane.YAxis.Scale.MajorUnit = DateUnit.Minute;
            myPane.YAxis.Scale.MinorUnit = DateUnit.Second;
            myPane.XAxis.IsVisible = false;
            myPane.X2Axis.IsVisible = true;
            myPane.X2Axis.MajorGrid.IsVisible = true;
            myPane.X2Axis.Scale.Min = 0;
            myPane.X2Axis.Scale.Max = 600;
            myPane.YAxis.Scale.Format = "HH:mm:ss";
            PointPairList list = new PointPairList();
            PointPairList list2 = new PointPairList();
            for (int i = 0; i < 36; i++)
            {
                double x = (double)i * 5.0;
                double y = (double)new XDate(DateTime.Now.AddSeconds(i));
                list.Add(y, x);
                //list2.Add(y2, x);
                listBox1.Items.Add("x = " + x + " y = " + y);
            }

            // Generate a red curve with diamond symbols, and "Alpha" in the legend
            LineItem myCurve = myPane.AddCurve("Alpha",
                list, Color.Red, SymbolType.None);
            // Fill the symbols with white
            myCurve.Symbol.Fill = new Fill(Color.White);
                        myPane.Y2Axis.MajorGrid.IsVisible = true;
            // Align the Y2 axis labels so they are flush to the axis
            myPane.Y2Axis.Scale.Align = AlignP.Inside;

            // Fill the axis background with a gradient
            myPane.Chart.Fill = new Fill(Color.White, Color.LightGray, 45.0f);
            zg1.IsShowPointValues = true;
            zg1.AxisChange();
            // Make sure the Graph gets redrawn
            zg1.Invalidate();

But I take something wrong: enter image description here

UPD2:

I have code for multithreading:

private TimerCallback ReadTimerCallback;
        private LineItem myCurve;
        private Random rnd = new Random(500);
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            GraphPane myPane = zg1.GraphPane;

            myPane.XAxis.IsVisible = false;

            myPane.X2Axis.IsVisible = true;
            myPane.X2Axis.MajorGrid.IsVisible = true;
            myPane.X2Axis.Scale.Min = 0;
            myPane.X2Axis.Scale.Max = 600;

            myPane.YAxis.IsVisible = false;

            myPane.Y2Axis.IsVisible = true;
            myPane.Y2Axis.Scale.MajorUnit = DateUnit.Minute;
            myPane.Y2Axis.Scale.MinorUnit = DateUnit.Second;
            myPane.Y2Axis.Scale.Format = "HH:mm:ss";
            myPane.Y2Axis.Type = AxisType.DateAsOrdinal;

            // As we get more data we want to add it on to the end of the curve
            // and we also want to get the scale so that we can shift it along
            double? oringinalLastDate;
            XDate firstDate;
            if (myPane.CurveList.Count == 0)
            {
                myCurve = myPane.AddCurve("Alpha",
                                          new PointPairList(),
                                          Color.Red,
                                          SymbolType.None);
                firstDate = new XDate(DateTime.Now);
                oringinalLastDate = null;
            }
            else
            {
                myCurve = (LineItem)myPane.CurveList[0];
                firstDate = myCurve.Points[myCurve.Points.Count - 1].Y;
                oringinalLastDate = myPane.Y2Axis.Scale.Max;
            }

            /*for (int i = 0; i < 36; i++)
            {
                double x = i * 5.0;
                firstDate.AddSeconds(i);

                myCurve.AddPoint(x, firstDate);

                //listBox1.Items.Add("x = " + x + " y = " + firstDate);
            }*/

            myCurve.Symbol.Fill = new Fill(Color.White);
            myCurve.IsX2Axis = true;
            myCurve.IsY2Axis = true;
            //myPane.Y2Axis.Scale.IsReverse = true;

            myPane.Chart.Fill = new Fill(Color.White, Color.LightGray, 45.0f);
            zg1.IsShowPointValues = true;

            // Now make the minimum of the scale, the maximum that it was so
            // the graph shifts
            if (oringinalLastDate.HasValue)
                myPane.Y2Axis.Scale.Min = oringinalLastDate.Value;

            zg1.AxisChange();
            zg1.Invalidate();
            AutoResetEvent ReadautoEvent = new AutoResetEvent(false);
            ReadTimerCallback = new TimerCallback(this.ShowData);
            System.Threading.Timer timer = new System.Threading.Timer(ReadTimerCallback, ReadautoEvent, 100, 1000);

        }

        private void ShowData (object Object )
        {
            this.myCurve.AddPoint(rnd.Next(500, 600), new XDate(DateTime.Now));
        }

UPD3: I want to move down Y axis, not scale this axis. And I have updated chart only 1 minute: enter image description here

Stamina answered 16/4, 2012 at 9:55 Comment(0)
F
3

I think you want DateAsOrdinal (instead of Date), to give you better date representations (though maybe not if you are happy with it) and you need to set the IsX2Axis and IsY2Axis properties on the curve to true.

Here is an updated version of your code that shows what I mean - is this what you need? (it will not be a wavy line like you have drawn given the data values and the x axis scale starts at 0 not 100 as in your drawing but that is because your code had it explicitly set to 0 so I am assuming that is what you want).

It will always append more data every time it is called (I am assuming you are calling it from your button1) and it will shift the minimum value for the axis along so you are showing just the most recent bit of data - if you do not set the Min value you will see a wobbly line as it is showing all the data.

GraphPane myPane = zg1.GraphPane;            

myPane.XAxis.IsVisible = false;

myPane.X2Axis.IsVisible = true;
myPane.X2Axis.MajorGrid.IsVisible = true;
myPane.X2Axis.Scale.Min = 0;
myPane.X2Axis.Scale.Max = 600;

myPane.YAxis.IsVisible = false;

myPane.Y2Axis.IsVisible = true;
myPane.Y2Axis.Scale.MajorUnit = DateUnit.Minute;
myPane.Y2Axis.Scale.MinorUnit = DateUnit.Second;
myPane.Y2Axis.Scale.Format = "HH:mm:ss";
myPane.Y2Axis.Type = AxisType.DateAsOrdinal;

// As we get more data we want to add it on to the end of the curve
// and we also want to get the scale so that we can shift it along
double? oringinalLastDate;
XDate firstDate;
LineItem myCurve;
if(myPane.CurveList.Count == 0)
{
    myCurve = myPane.AddCurve("Alpha",
                              new PointPairList(),
                              Color.Red,
                              SymbolType.None);
    firstDate = new XDate(DateTime.Now);
    oringinalLastDate = null;
}
else
{
    myCurve = (LineItem)myPane.CurveList[0];
    firstDate = myCurve.Points[myCurve.Points.Count - 1].Y;
    oringinalLastDate = myPane.Y2Axis.Scale.Max;
}            

for (int i = 0; i < 36; i++)
{
    double x = i * 5.0;
    firstDate.AddSeconds(i);

    myCurve.AddPoint(x, firstDate);

    listBox1.Items.Add("x = " + x + " y = " + firstDate);
}

myCurve.Symbol.Fill = new Fill(Color.White);
myCurve.IsX2Axis = true;
myCurve.IsY2Axis = true;

myPane.Chart.Fill = new Fill(Color.White, Color.LightGray, 45.0f);
zg1.IsShowPointValues = true;

// Now make the minimum of the scale, the maximum that it was so
// the graph shifts
if (oringinalLastDate.HasValue)
    myPane.Y2Axis.Scale.Min = oringinalLastDate.Value;

zg1.AxisChange();            
zg1.Invalidate();

Update

If you want to update the chart once a second with a random number between 500 and 600 this should do it (after every 3 points are added, the scale on the y axis moves along):

private int pointCount;
private double? scaleMin = null;
private static readonly Random rnd = new Random();

private void button1_Click(object sender, EventArgs e)
{
    GraphPane myPane = zg1.GraphPane;

    myPane.XAxis.IsVisible = false;

    myPane.X2Axis.IsVisible = true;
    myPane.X2Axis.MajorGrid.IsVisible = true;
    myPane.X2Axis.Scale.Min = 0;
    myPane.X2Axis.Scale.Max = 600;

    myPane.YAxis.IsVisible = false;

    myPane.Y2Axis.IsVisible = true;
    myPane.Y2Axis.Scale.MajorUnit = DateUnit.Minute;
    myPane.Y2Axis.Scale.MinorUnit = DateUnit.Second;
    myPane.Y2Axis.Scale.Format = "HH:mm:ss";
    myPane.Y2Axis.Type = AxisType.DateAsOrdinal;

    LineItem myCurve = myPane.AddCurve("Alpha",
                                  new PointPairList(),
                                  Color.Red,
                                  SymbolType.None);

    myCurve.Symbol.Fill = new Fill(Color.White);
    myCurve.IsX2Axis = true;
    myCurve.IsY2Axis = true;

    myPane.Chart.Fill = new Fill(Color.White, Color.LightGray, 45.0f);
    zg1.IsShowPointValues = true;

    pointCount = 0;

    var t = new System.Windows.Forms.Timer();
    t.Interval = 1000;
    t.Tick += ShowData;

    Thread.Sleep(100);

    t.Start();
}

private void ShowData(object sender, EventArgs e)
{
    var t = (System.Windows.Forms.Timer) sender;
    t.Enabled = false;

    pointCount++;

    int x = rnd.Next(500, 600);
    var y = new XDate(DateTime.Now);

    GraphPane myPane = zg1.GraphPane;

    if (scaleMin == null) scaleMin = myPane.Y2Axis.Scale.Max;

    LineItem myCurve = (LineItem)myPane.CurveList[0];            

    myCurve.AddPoint(x, y);

    // After 3 points are added move the scale along
    if (pointCount > 3)
    {
        myPane.Y2Axis.Scale.Min = scaleMin.Value;
        scaleMin = myPane.Y2Axis.Scale.Max;
    }

    zg1.AxisChange();
    zg1.Invalidate();

    t.Enabled = true;
}
Fumy answered 16/4, 2012 at 11:36 Comment(13)
Thanks kmp! This is what I need, but I want to make time axis in motion, for visualize real time data. How to make this?Stamina
I have updated the answer - hopefully I have understood you - the data gets added each time the code is called now and the minimum axis point is adjusted so you will see the last 35 seconds of data.Fumy
1. I must add new datas with myCurve.AddPoint(x, firstDate) and set minimum of scale by myPane.Y2Axis.Scale.Min = oringinalLastDate.Value ? 2. Can I add points to myCurve from another thread?Stamina
1. Yes, that is what I did since I wanted to show you keeping all the data plotted by the graph and just shifting the axis. This way if you like you can just not set the Min valud and you will see all the data as it is added. Altenatively you can just use the original mechanism and start with an empty list of points each time. 2. Yes, you can do that - all of the code in the sample I gave could be run in a different thread except for the line where the item is added to the listBox - you would need to call Invoke there.Fumy
I try to add points to myCurve in timer which raised every 1 second, but points aren't show in chart. What I do wrong? I have updated question.Stamina
You just need to Invalidate the chart when you add to it - added a second example to my answer.Fumy
Thanks kmp! I want to move down Y axis, not scale this axis. And a chart draw only little more 1 minute then stoping. See UPD3. Thanks.Stamina
OK, you can use the technique I showed you in the first example to do that (I have updated the second example now so that after three points are added the scale moves). I changed the timer to use a windows forms timer which lets you stop and start it easier so now it should just tick on forever updating every second and showing the most recent three values (you can see how to adjust these settings in the code).Fumy
Thank you kmp from Russia, Tatarstan (from Naberezhnye chelny)! And one little question: Hot to in Y2Axis show for example last 1 hour and not scale axis, just move slowly down (when new point inserted)?Stamina
That I do not know - I think you may be better to ask a specific separate question for that along the lines of "how do I set the min and max values on a scale based on a date and time?". I used the trick of counting the values, but that was because when I set the Min value to a date it died. If you know how many values per hour you were getting you could just change that 3 in the code to that and it would do what you ask, I think but it would be nicer if you could set Min to DateTime.Now.AddHours(-1), for example (but I couldn't work it out)Fumy
Ok, I try to ask question about "how do I set the min and max values on a scale based on a date and time?"Stamina
Well, I asked question #10223282Stamina
Dear kmp! Can you help me to get to the end of this question #10223282Stamina

© 2022 - 2024 — McMap. All rights reserved.