1

I've created a program that reads in a text file and displays the data from that file into a DataGridView; I then use the data from this DGV to update a 'chart' based on the results, the chart only consists of line graphs.

What I'm trying to accomplish is allowing the user to select a portion of that data my dragging a beginning and end over it like you would to zoom in if only the x axis was enabled, and update the the graph based on that selection, calculating averages for this subset of data.

Using

chart1.ChartAreas["ChartArea1"].CursorX.IsUserEnabled = Enabled;
chart1.ChartAreas["ChartArea1"].CursorX.IsUserSelectionEnabled = Enabled;

This allows me to select the area and zoom in but I'm unsure how to actually update the data based on the selection rather than just zoom.

TaW
  • 53,122
  • 8
  • 69
  • 111
Dave Jones
  • 53
  • 10
  • Sounds like a Duplicate of [this](http://stackoverflow.com/questions/29985796/chart-zoom-in-to-show-more-precise-data/29986941#29986941) - when you zoom the graph is updating itself autmatically. What if any do you want beyond that? What is it you want with the averages you mention?? – TaW May 05 '15 at 15:42
  • It gathers the averages by iterating through how many rows there are which make up the graph, so for example if there are 3000 rows, it will then run from 0 - 3000 and divide by 3000, however by just zooming in this isn't going to update the X axis max and minimum it will simply show a zoomed in view. If it was selected from half way to the end so, min = 1500 and max = 3000 then obviously it would be something like for (i = min, i < max, i++) but I need a way to update them values. – Dave Jones May 05 '15 at 16:28
  • I'm still not quite sure: Is the avarage part of the chart or do you show it somewhere else? and: When the view is zoomed, do you want the average only calculated from the visible points? – TaW May 05 '15 at 17:57
  • I show it elsewhere for the average for the entire thing but I will update it next to the graph once the selection is updated, yes that's correct :) – Dave Jones May 05 '15 at 18:07
  • And that would mean that yo need to update the avg. when zooming in or out and also when scrolling, right? So what you need is a way to get at the index of the first and last visible points? See [here](http://stackoverflow.com/questions/29822227/get-points-on-a-zoomed-view-on-ms-chart/29828923?s=11|0.0000#29828923) for a solution! - You can code the [Chart.AxisViewChanged Event](https://msdn.microsoft.com/en-us/library/system.windows.forms.datavisualization.charting.chart.axisviewchanged%28v=vs.110%29.aspx) to do the new calculation.. – TaW May 05 '15 at 18:17

1 Answers1

0

To allow nice zooming you should add this line to the two you show:

chart1.ChartAreas["ChartArea1"].AxisX.ScaleView.Zoomable = true;

Here is a function to calculate an average of the visible points' 1st YValues:

private void chart1_AxisViewChanged(object sender, ViewEventArgs e)
{
    // for a test the result is shown in the Form's title
    Text = "AVG:" + GetAverage(chart1, chart1.Series[0], e);
}

double GetAverage(Chart chart, Series series, ViewEventArgs e)
{
    ChartArea CA = e.ChartArea;  // short..
    Series S = series;           // references  

    DataPoint pt0 = S.Points.Select(x => x)
                            .Where(x => x.XValue >= CA.AxisX.ScaleView.ViewMinimum)
                            .DefaultIfEmpty(S.Points.First()).First();
    DataPoint pt1 = S.Points.Select(x => x)
                            .Where(x => x.XValue <= CA.AxisX.ScaleView.ViewMaximum)
                            .DefaultIfEmpty(S.Points.Last()).Last();
    double sum = 0;
    for (int i = S.Points.IndexOf(pt0); i < S.Points.IndexOf(pt1); i++) 
       sum += S.Points[i].YValues[0];

    return sum / (S.Points.IndexOf(pt1) - S.Points.IndexOf(pt0) + 1);
}

Note that the ViewEventArgs parameter is providing the values of the position and size of the View, but these are just the XValues of the datapoints and not their indices; so we need to search the Points from the left for the 1st and from right for the last point.

Update Sometimes the zooming runs into a special problem: When the data are more finely grained than the default CursorX.IntervalType it just won't let you zoom. In such a case you simply have to adapt to the scale of your data, e.g. like this: CA.CursorX.IntervalType = DateTimeIntervalType.Milliseconds;

TaW
  • 53,122
  • 8
  • 69
  • 111
  • I implemented this and nothing updated in the Form's title, I'm now using a tooltip which displays the averages upon highlighting the line and have five series which do this. Would it be possible to get the updated version to show here? – Dave Jones May 06 '15 at 14:13
  • _nothing updated in the Form's title_ Have you hooked up the `AxisViewChanged` event? – TaW May 06 '15 at 15:01
  • _I'm now using a tooltip which displays the averages upon highlighting the line_ please explain what these two things mean! What do you mean by highlighting? dragging over the chart with the mouse? Does your tooltip show? – TaW May 06 '15 at 15:03
  • Ah rookie mistake, I hadn't no, an average now does appear but doesn't change when selecting again. Yes placing my mouse cursor over a line, the tooltip does show and shows the average like so "Average:#AVG", thank you for your help so far. – Dave Jones May 06 '15 at 15:56
  • _doesn't change when selecting again_ By selecting you mean dragging with the left mouse button, right? When the zoom changes or also, when you scroll in the zoomed view with the scrollbar, the event AxisViewChanged should fire. Does it? If so the average will be recalculated but may still stay the same, if th enumbers don't change or change enough.. – TaW May 06 '15 at 16:04
  • Note that afaik the #AVG function will display the average over all points, not just those in the view! – TaW May 06 '15 at 16:06
  • Neither scrolling with the scrollbar or dragging with the left mouse button, yes, trigger the event again, the result stays the same, I think the average that is returning is the average for everything. Yeah I realise that, I was just wondering whether it was possible to update that when zoomed in, if not, it's not an issue! – Dave Jones May 06 '15 at 16:16
  • The above code calculates the average only from the visible points and updates on each scroll or zoom. Can you insert a `Console.WriteLine("Points from :" + S.Points.IndexOf(pt0) + " to " + Points.IndexOf(pt1))` ? it should show you which points are visible. Is the average from the GetAverage function the same as from the #AVG function? – TaW May 06 '15 at 16:25
  • Yeah that's what I'm wanting it to do, however the result is "Points from :0 to 3978" Which is the entire range so it mustn't be updating correctly, yes thats correct. – Dave Jones May 06 '15 at 16:31
  • _the result is "Points from :0 to 3978"_ Hm, that's the same even though the view is zoomed in and each time you scroll, always the same?? – TaW May 06 '15 at 16:45
  • Question: Are the xValues in your series ascending? – TaW May 06 '15 at 17:18
  • Always the same yeah, now that you mention it no they weren't, stayed the same, I've used x++; now and the results are updating, never even thought about that! I believe it's working correctly now then, thank you! – Dave Jones May 06 '15 at 17:31
  • The only thing I could comment on though is that it seems to be really slow when going onto the graph page now and seems to be using a lot of resources. – Dave Jones May 06 '15 at 18:01
  • About how many Points are in the series and how many are visible – TaW May 06 '15 at 19:03
  • Forget it, I remembered that you have ca 4000 points. Ok, that is some work to search through. When and if I can think of a way to speed this up I'll pdate you. If it is too sluggish, you could instead of updating all the time give the user a button to refresh the average. - OTOH if many points are visible, then maybe the calculation takes a lot of time as well; that can't really be helped.. – TaW May 06 '15 at 19:18
  • Actually after playing around with a few things, commenting things out etc. I think it's just the general loading speed of the graph which is slow. – Dave Jones May 06 '15 at 19:27
  • I have just added 4000 points to my chart and find that scrolling is rather fast when zoomed in a lot. If I zoom in just a little the calculation seems to take noticable time; not terrible but qite different from the real-time feeling in deeper zoom levels.. But the serch is always fast enough. Of course loading can't be sped up, other that using suspend- and resumelayout during load. – TaW May 06 '15 at 19:31