如何在散点图中绘制超过50,000个值,从而节省计算机资源?

时间:2017-06-29 15:42:39

标签: c# .net winforms charts mschart

我正在使用Visual Studio 2017,并尝试使用C#和winform创建一个在散点图中显示实时值的程序。

使用下面的源代码,我可以让它显示实时值,无论何时发生事件并且它获得一个新值(每秒3~5次)。

valueArray通过GetRealTimeData函数不断获取新值,图表显示数组中的所有元素。

        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);

但是,我在使用这个程序时遇到了问题,即使它在图表中显示3,000个值,它也会消耗大量的计算机资源。

我计划让图表代表50,000到100,000个值,但我认为它会耗费太多的资源复制并在每次获得新值时显示旧值。

我想知道是否有任何功能或方法可以完成这类工作。如果我能得到一些建议或想法,我将不胜感激。

1 个答案:

答案 0 :(得分:2)

我几乎没有任何理由可以加载任何超过100,000点的图表。您可以使用原始积分的一小部分来展示您的数据,而不会丢失视觉信息。这是一个过滤100,000点至250点(0.25%)的样本:

enter image description here

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;
        }
    }
}

我理解你是动态添加点,所以你必须为它添加一些逻辑。但我的观点仍然存在:您必须过滤您的数据。此外,您可以使用更复杂的过滤器,如果您能想出一个。