public TimeStampDataEntity(PlotManager plotManager, DataEntityInfo dataInfo, int sampleCount) : base(plotManager, dataInfo) { _samplesInChart = 0; _singleSamplePlotMode = (sampleCount == 1); if (_singleSamplePlotMode) { _timeStamps = new List <DateTime>(dataInfo.Capacity); _blockCounts = null; _isEven = true; } else { _timeStamps = new List <DateTime>(dataInfo.Capacity / sampleCount); _blockCounts = new List <int>(dataInfo.Capacity / sampleCount); _isEven = true; } _yBuffers = new List <OverLapWrapBuffer <TDataType> >(DataInfo.LineCount); for (int i = 0; i < DataInfo.LineCount; i++) { _yBuffers.Add(new OverLapWrapBuffer <TDataType>(DataInfo.Capacity)); } _plotBuffer = new PlotBuffer <TDataType>(DataInfo.LineCount, DataInfo.Capacity); }
public StringDataEntity(PlotManager plotManager, DataEntityInfo dataInfo) : base(plotManager, dataInfo) { _xBuffer = new OverLapStrBuffer(DataInfo.Capacity); _yBuffers = new List <OverLapWrapBuffer <TDataType> >(DataInfo.LineCount); for (int i = 0; i < DataInfo.LineCount; i++) { _yBuffers.Add(new OverLapWrapBuffer <TDataType>(DataInfo.Capacity)); } _plotBuffer = new PlotBuffer <TDataType>(DataInfo.LineCount, DataInfo.Capacity); }
public ParallelHandler(DataEntity dataEntity, DataCheckParameters dataCheckParams) { this._dataEntity = dataEntity; this._buffer = dataEntity.PlotBuf; this._option = new ParallelOptions(); this._indexOffset = 0; this._dataCheckParams = dataCheckParams; // 计算限制型配置并行度为内核个数 _option.MaxDegreeOfParallelism = Environment.ProcessorCount; this._maxDatas = new double[_option.MaxDegreeOfParallelism]; this._minDatas = new double[_option.MaxDegreeOfParallelism]; }
public IndexDataEntity(PlotManager plotManager, DataEntityInfo dataInfo) : base(plotManager, dataInfo) { _plotManager = plotManager; this._startIndex = _plotManager.StartIndex; this._nextIndex = _plotManager.StartIndex; this._plotBuffer = new PlotBuffer <TDataType>(DataInfo.LineCount, DataInfo.Capacity); _yBuffers = new List <OverLapWrapBuffer <TDataType> >(DataInfo.LineCount); for (int i = 0; i < DataInfo.LineCount; i++) { _yBuffers.Add(new OverLapWrapBuffer <TDataType>(DataInfo.Capacity)); } }
// TODO 后期优化,记录当前Series的Plot范围,然后再判断是否需要重新Plot // 在begin和end区间内绘制单条曲线,分区视图使用。如果forceRefresh为true时(调用Plot方法时)始终更新绘图。 // 如果forceRefresh为false时(用户进行缩放等操作时)如果判断数据区间和原来的兼容(稀疏比相同且是上次绘图范围的子集则无需更新) // 使用forceRefresh是为了避免在数据量过大,用户缩放后拖动滚动条会比较卡顿的问题 internal void PlotDataInRange(double beginXValue, double endXValue, int seriesIndex, bool forceRefresh, bool isLogView) { int lineIndex; DataEntity dataEntity = GetDataEntityBySeriesIndex(seriesIndex, out lineIndex); if (null == dataEntity) { return; } bool isNeedRefreshPlot = dataEntity.FillPlotDataInRange(beginXValue, endXValue, forceRefresh, lineIndex, isLogView); if (isNeedRefreshPlot) { PlotBuffer plotBuffer = dataEntity.PlotBuf; if (PlotSeries[seriesIndex].Points.Count == plotBuffer.PlotSize) { for (int i = 0; i < plotBuffer.PlotSize; i++) { double yValue = plotBuffer.YPlotBuffer[lineIndex][i]; PlotSeries[seriesIndex].Points[i].SetValueXY(plotBuffer.XPlotBuffer[i], yValue); if (PlotSeries[seriesIndex].Points[i].IsEmpty && !double.IsNaN(yValue)) { PlotSeries[seriesIndex].Points[i].IsEmpty = false; } } } else { IList <double> xDataBuf = plotBuffer.GetXPlotDataCollection(); IList <double> yDataBuf = plotBuffer.GetYPlotDataCollection(lineIndex); PlotSeries[seriesIndex].Points.DataBindXY(xDataBuf, yDataBuf); } // 如果有校验Nan数据,则将标记为Nan数据的点不显示 if (DataCheckParams.CheckNaN) { HideNanDataPoint(seriesIndex); } //if (dataEntity.DataInfo.XDataType != XDataType.Number) //{ // RefreshTimeToXLabel(seriesIndex); //} } }
// 在begin和end区间内绘制所有曲线,在主视图使用。如果forceRefresh为true时(调用Plot方法时)始终更新绘图。 // 如果forceRefresh为false时(用户进行缩放等操作时)如果判断数据区间和原来的兼容(稀疏比相同且是上次绘图范围的子集则无需更新) // 使用forceRefresh是为了避免在数据量过大,用户缩放后拖动滚动条会比较卡顿的问题 internal void PlotDataInRange(double beginXValue, double endXValue, bool forceRefresh, bool isLogView) { int seriesIndex = 0; foreach (DataEntity dataEntity in PlotDatas) { // 根据begin和end的范围,将数据填充到PlotBuffer中。如果无需更新绘图则返回false。 bool isNeedRefreshPlot = dataEntity.FillPlotDataInRange(beginXValue, endXValue, forceRefresh, -1, isLogView); PlotBuffer plotBuffer = dataEntity.PlotBuf; if (isNeedRefreshPlot) { bool pointCountChanged = false; for (int i = seriesIndex; i < seriesIndex + dataEntity.DataInfo.LineNum; i++) { if (PlotSeries[i].Points.Count != plotBuffer.PlotSize) { pointCountChanged = true; break; } } //如果点的个数和上次相同,则直接使用PlotBuffer的数据直接更新点的数据 if (!pointCountChanged) { for (int lineIndex = 0; lineIndex < dataEntity.DataInfo.LineNum; lineIndex++) { for (int i = 0; i < plotBuffer.PlotSize; i++) { double yValue = plotBuffer.YPlotBuffer[lineIndex][i]; PlotSeries[seriesIndex].Points[i].SetValueXY(plotBuffer.XPlotBuffer[i], yValue); if (PlotSeries[seriesIndex].Points[i].IsEmpty && !double.IsNaN(yValue)) { PlotSeries[seriesIndex].Points[i].IsEmpty = false; } } // 如果有校验Nan数据,则将标记为Nan数据的点不显示 if (DataCheckParams.CheckNaN) { HideNanDataPoint(seriesIndex); } seriesIndex++; } } // 如果点的个数和上次不同,则使用数据绑定,则获取当前点的数据集合,直接绑定点的数据到Chart else { IList <double> xDataBuf = plotBuffer.GetXPlotDataCollection(); IList <IList <double> > yDataBuf = plotBuffer.GetYPlotDataCollections(); for (int lineIndex = 0; lineIndex < dataEntity.DataInfo.LineNum; lineIndex++) { PlotSeries[seriesIndex].Points.DataBindXY(xDataBuf, yDataBuf[lineIndex]); // 如果有校验Nan数据,则将标记为Nan数据的点不显示 if (DataCheckParams.CheckNaN) { HideNanDataPoint(seriesIndex); } seriesIndex++; } } } else { seriesIndex += dataEntity.DataInfo.LineNum; } } }
public List <PlotItemGroup> RenderAllGroups(StackPanel panel, double plotHeight) { // first access var res = new List <PlotItemGroup>(); if (panel == null) { return(null); } panel.Children.Clear(); // before applying arguments _autoScaleX = true; _autoScaleY = true; // go over all groups ScottPlot.WpfPlot lastPlot = null; foreach (var groupPI in GetItemsGrouped()) { // start new group var pvc = new WpfPlotViewControlHorizontal(); pvc.Text = "Single value plot"; if (groupPI.Group >= 0 && groupPI.Group < 9999) { pvc.Text += $"; grp={groupPI.Group}"; } var wpfPlot = pvc.WpfPlot; // some basic attributes lastPlot = wpfPlot; wpfPlot.plt.AntiAlias(false, false, false); wpfPlot.AxisChanged += (s, e) => WpfPlot_AxisChanged(wpfPlot, e); groupPI.WpfPlot = wpfPlot; res.Add(groupPI); // for all wpf / all signals pvc.Height = plotHeight; pvc.ButtonClick += WpfPlot_ButtonClicked; // for each signal double?yMin = null, yMax = null; foreach (var pi in groupPI) { // value var val = pi.SME?.ValueAsDouble(); // integrate args if (pi.Args != null) { if (pi.Args.ymin.HasValue) { yMin = Nullable.Compare(pi.Args.ymin, yMin) > 0 ? pi.Args.ymin : yMin; } if (pi.Args.ymax.HasValue) { yMax = Nullable.Compare(yMax, pi.Args.ymax) > 0 ? yMax : pi.Args.ymax; } } // prepare data var pb = new PlotBuffer(); pi.Buffer = pb; // factory new Plottable pb.Plottable = wpfPlot.plt.PlotSignal(pb.BufferData, label: "" + pi.DisplayPath); pb.Push(val.HasValue ? val.Value : 0.0); } // apply some more args to the group if (yMin.HasValue) { wpfPlot.plt.Axis(y1: yMin.Value); _autoScaleY = false; } if (yMax.HasValue) { wpfPlot.plt.Axis(y2: yMax.Value); _autoScaleY = false; } // render the plot into panel wpfPlot.plt.Legend(fontSize: 9.0f); panel.Children.Add(pvc); wpfPlot.Render(skipIfCurrentlyRendering: true); } // for the last plot .. if (lastPlot != null) { lastPlot.plt.XLabel("Samples"); } // return groups for notice return(res); }