I'm using Visual Studio 2017 and am trying to make a program that shows real-time values in a scatter chart, using C# and winform.
With the source code below, I was able to make it show real-time values, whenever an event occurs and it gets a new value(3~5 times a second).
valueArray continuously gets new values through GetRealTimeData function and the chart shows all the elements in the array.
valueArray[valueArray.Length - 1] = Convert.ToDouble(GetRealTimeData().Trim());
Array.Copy(valueArray, 1, valueArray, 0, valueArray.Length - 1);
this.chart1.Series["Series1"].Points.Clear();
this.chart1.Series["Series1"].Points.DataBindY(valueArray);
However, I have a problem using this program, which is it consumes much computer resource even when it shows 3,000 values in the chart.
I plan to make the chart represent 50,000 to 100,000 values, but I think it uses up too much resource copying and showing old values everytime it gets a new value.
I'd like to know if there are any functions or methods to do this kind of job. I would appreciate it if I could get some advices or ideas.
There's hardly any reason that I know of, to ever load any chart with 100,000+ points. You can present your data using a fraction of your original points, without any loss of visual information . Here's a sample filtering 100,000 points down to 250 points (0.25%):
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
double percent = 0.0025;
List<DataPoint> original = GetData();
List<DataPoint> filtered = Filter(original, percent);
foreach (DataPoint dp in original)
chart1.Series[0].Points.Add(dp);
foreach (DataPoint dp in filtered)
chart1.Series[1].Points.Add(dp);
chart1.ChartAreas[0].AxisY.Maximum = original.Max(dp => dp.YValues[0]);
chart1.ChartAreas[0].AxisY.Minimum = original.Min(dp => dp.YValues[0]);
chart1.ChartAreas[0].AxisX.Minimum = 0;
Text = string.Format("original = {0:0,0} points, filtered = {1:0,0} points, percent = {2:P2}", original.Count, filtered.Count, percent);
}
private List<DataPoint> Filter(List<DataPoint> orig, double percent)
{
Random r = new Random(DateTime.Now.Millisecond);
List<DataPoint> filt = new List<DataPoint>(orig.ToArray());
double total = filt.Count;
while (filt.Count / total > percent)
filt.RemoveAt(r.Next(1, filt.Count - 1));
return filt;
}
private void button1_Click(object sender, EventArgs e)
{
if (chart1.Series[0].Enabled)
{
chart1.Series[0].Enabled = false;
chart1.Series[1].Enabled = true;
}
else
{
chart1.Series[0].Enabled = true;
chart1.Series[1].Enabled = false;
}
}
}
I understand you're adding points dynamically, so you'll have to add some logic to it. But my point still stands: you must filter your data. Also, you can use a more sophisticated filter, if you can come up with one.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.