簡體   English   中英

將點添加到圖表的左側

[英]Adding points to the left side of a chart

在WinForms中,我正在嘗試創建一個交互式圖表,但我遇到了一個方面的困難。 我正在使用System.Windows.Forms.DataVisualization.Charting.Chart作為圖表,並使用FastLine系列來呈現數據。

在此圖表中,您可以縮放/平移/更改通道,並根據需要動態添加/刪除新點。 原因是這些點的來源是一個大的二進制文件,可以超過一千兆字節,我使用MemoryMappedFile來提取盡可能少的數據來提高性能。

當向右平移時,一切正常 - 新的點被添加到列表的末尾,你甚至不能說它們在一秒鍾之前就不存在了。

但是,當我向左平移時,圖表以非常奇怪的方式顯示。 整條地方都有線路。 我知道這里發生了什么,我無法弄清楚如何解決它。

原因是當添加一個點時,從添加到新點的最后一個點繪制一條線。 因此,如果最后一個點被添加到右側,並且新點被添加到左側,則一條線將穿過圖形。

以下是為圖表添加點的代碼:

for (var i = scanStart; i + _step <= scanEnd; i += _step)
{
   var sample = _expeData.ReadSample(channel, i);
   Series[0].Points.AddXY(i, sample);
}

有沒有辦法防止這種情況發生? 這是一個屏幕截圖,顯示向左平移后的樣子:

在此輸入圖像描述

我決定嘗試使用LINQ來處理排序。

        // Suspend updates prior to insertion to speed everything up
        chart1.Series[0].Points.SuspendUpdates();

        // Do a quicky population for testing purposes
        for (int i = 0; i < 100; i++)
        {
            chart1.Series[0].Points.AddXY(i, i);
        }
        for (int i = -100; i < 0; i++)
        {
            chart1.Series[0].Points.AddXY(i, -i * 2);
        }

        // Sort the data points
        var newDataPoints =
            (from d in chart1.Series[0].Points
             orderby d.XValue
             select new { XValue = d.XValue, YValue = d.YValues[0] }).ToList();

        // Replace the datapoints
        chart1.Series[0].Points.DataBind(newDataPoints, "XValue", "YValue", "");

        // Turn updates back on
        chart1.Series[0].Points.ResumeUpdates();

這是一個很酷的控制,我以前從未注意過。 請不要將我的帖子標記為答案。 它只是大聲說話。

你能清除圖表並在LEFT PAN上重新分配數據嗎?

您可以向您的類聲明一些全局變量:

private int x_index;
private DataTable m_dataTable;

在Chart的構造函數中,連接AxisViewChanging和AxisViewChanged事件處理程序:

public Form1() {
  InitializeComponent();
  x_index = -1;
  if (graph1.Series == null) {
    graph1.Series = new SeriesCollection();
  }
  graph1.AxisViewChanging += new EventHandler<ViewEventArgs>(graph1_AxisViewChanging);
  graph1.AxisViewChanged += new EventHandler<ViewEventArgs>(graph1_AxisViewChanged);
}

現在,修改Get Data例程以將數據收集到新的DataTable中:

private void GetData(string channel, int scanStart, int step, int scanEnd) {
  m_dataTable = new DataTable();
  var col1 = m_dataTable.Columns.Add("Index", typeof(int));
  var col2 = m_dataTable.Columns.Add("Data", typeof(Series));
  for (var i = scanStart; i + step <= scanEnd; i += step) {
    var sample = _expeData.ReadSample(channel, i);
    var row = m_dataTable.NewRow();
    row[col1] = i;
    row[col2] = new Series(sample);
    m_dataTable.Rows.Add(row);
  }
}

下面的更改處理程序只記錄您當前的索引:

private void graph1_AxisViewChanging(object sender, ViewEventArgs e) {
  // below is probably wrong, but basically, get the x_axis before the data changes
  x_index = Convert.ToInt32(graph1.Series[0].XValueMember);
}

下面的Changed處理程序用於顯示您在上面收集的x_index之前的數據:

private void graph1_AxisViewChanged(object sender, ViewEventArgs e) {
  var index = Convert.ToInt32(graph1.Series[0].XValueMember);
  if (index < x_index) {
    graph1.Series.Clear();
    for (int i = index; i < index + 50; i++) {
      var pt = (Series)m_dataTable.Rows[i]["Data"];
      graph1.Series.Add(pt);
    }
  }
}

在上面,值50將是您想要計算的任何值。 它應該在代碼中的某處確定為變量或常量,以使其看起來不像幻數。

我不確定這是否符合您的要求。

如果是這樣的話,當有人平移時,需要調整它來計算你的價值 - 因為我的代碼可能會破壞這個功能。 ;)

您是否嘗試過使用InsetXY方法?

chart.Series[0].Points.InsertXY(0, i, sample)

有了它,你將始終添加到第一個位置。

不知道這是否適合你的問題。

我發現解決方案是使用Series [0] .Sort()函數。 我修改了原始代碼如下:

for (var i = scanStart; i + _step <= scanEnd; i += _step)
{
    var sample = _expeData.ReadSample(_channel, i);
    Series[0].Points.AddXY(i, sample);
}

Series[0].Sort(new PointComparer());

我添加了一個私有類來處理排序:

private class PointComparer : IComparer<DataPoint>
{
    public int Compare(DataPoint x, DataPoint y)
    {
        return (int)(x.XValue - y.XValue);
    }
}

這基於XValue對點進行排序。 當點數開始增長到大約40,000以上時,會有輕微的性能損失。 但是,我可以通過僅加載屏幕上可見的點(在現代寬屏顯示器上最多大約2,000點)然后在超過一定量(我使用20,000)時修剪來減輕這種情況。 這導致在相對大量的搖攝后偶爾出現打嗝,但這不是很明顯。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM