using ScottPlot.Plottable; using ScottPlot; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Navigation; using System.Windows.Shapes; using System.Drawing; using System.Reflection; using System.Windows.Threading; using Microsoft.Win32; using System.Windows.Media.Imaging; using mseedChart.Main.Models; using mseedChart.Main.ViewModels; using System.Security; namespace mseedChart.Main.Views { /// /// ChartPlot.xaml 的交互逻辑 /// public partial class ChartPlotView : UserControl { public DispatcherTimer _renderTimer = new DispatcherTimer(); //非定时更新需停止定时器 List scatterPlots = new List(); //每天生成的最大点数*1天 const int MaxPointCount = 30_000; int nextDataIndex = 1; WpfPlot pl; public ChartPlotView() { InitializeComponent(); //去掉右键菜单 plt.RightClicked-=plt.DefaultRightClickEvent; // plt.RightClicked+= RightClickEvent; var model = this.DataContext as ChartPlotViewModel; model.InializeChartPlotChange = InializeChartPlotDates; model.PlotLineDataChanged = PlotLineLiveData; plt.Plot.Palette = new ScottPlot.Palettes.ColorblindFriendly(); // plt.Configuration.LockVerticalAxis = true; List lineLabels; lineLabels = new List(); for (int i = 0; i < 72; i++) { lineLabels.Add(i.ToString()); } foreach (var item in lineLabels) { double[] data = new double[MaxPointCount]; var line = plt.Plot.AddSignal(data); line.Label = item; // line.Smooth = true; // line.SmoothTension = 0.6f; scatterPlots.Add(line); } plt.Refresh(); plt.Plot.XAxis.Color(Color.Black); plt.Plot.Legend(enable: false); // plt.Plot.Legend( false,location: Alignment.MiddleLeft); //X轴显示格式 // plt.Plot.XAxis.TickLabelFormat("yyyy-MM-dd HH:mm:ss", dateTimeFormat: true); _renderTimer.Interval = TimeSpan.FromMilliseconds(1000); _renderTimer.Tick += Render; _renderTimer.Start(); } void Render(object sender, EventArgs e) { if (AutoAxisCbox.IsChecked == true) { plt.Plot.AxisAuto(); } plt.Refresh(); } int index = 1; void PlotLineLiveData(List runData) { int number = runData[0].Length; for (int i = 0; i < scatterPlots.Count; i++) //数组平移 { // Array.Copy(scatterPlots[i].Xs, 1, scatterPlots[i].Xs, 0, scatterPlots[i].Xs.Length - 1); Array.Copy(scatterPlots[i].Ys, number, scatterPlots[i].Ys, 0, scatterPlots[i].Ys.Length - number); Array.Copy(runData[i], 0, scatterPlots[i].Ys, scatterPlots[i].Ys.Length - number, number); } } void InializeChartPlotDates(List lineDatas) { nextDataIndex = lineDatas[0].YData.Length; for (int i = 0; i < scatterPlots.Count; i++) { if (nextDataIndex <= MaxPointCount) { //内存拷贝 Array.Copy(lineDatas[i].YData, scatterPlots[i].Ys, nextDataIndex); scatterPlots[i].MaxRenderIndex = nextDataIndex-1; } else { // scatterPlots[i].OffsetX = lineDatas[0].XData[nextDataIndex - MaxPointCount]; // Set start date // Array.Copy(lineDatas[i].XData, nextDataIndex - MaxPointCount, scatterPlots[i].Xs, 0, MaxPointCount); Array.Copy(lineDatas[i].YData, nextDataIndex - MaxPointCount, scatterPlots[i].Ys, 0, MaxPointCount); scatterPlots[i].MaxRenderIndex = MaxPointCount-1; } } nextDataIndex = nextDataIndex < MaxPointCount ? nextDataIndex: MaxPointCount; //最大不能超过 MaxPointCount // plt.Plot.AxisAuto(); // plt.Refresh(); } private void OnMouseMove(object sender, MouseEventArgs e) { int pixelX = (int)e.MouseDevice.GetPosition(plt).X; int pixelY = (int)e.MouseDevice.GetPosition(plt).Y; (double coordinateX, double coordinateY) = plt.GetMouseCoordinates(); plt.Refresh(); } private void wpfPlot1_MouseEnter(object sender, MouseEventArgs e) { // MouseTrackLabel.Content = "Mouse ENTERED the plot"; // Crosshair.IsVisible = true; } private void wpfPlot1_MouseLeave(object sender, MouseEventArgs e) { //MouseTrackLabel.Content = "Mouse LEFT the plot"; //XPixelLabel.Content = "--"; //YPixelLabel.Content = "--"; //XCoordinateLabel.Content = "--"; //YCoordinateLabel.Content = "--"; // Crosshair.IsVisible = false; // plt.Refresh(); } public void RightClickEvent(object sender, EventArgs e) { var cm = new ContextMenu(); MenuItem SaveImageMenuItem = new() { Header = "保存图片" }; SaveImageMenuItem.Click += RightClickMenu_SaveImage_Click; cm.Items.Add(SaveImageMenuItem); MenuItem CopyImageMenuItem = new() { Header = "复制图片" }; CopyImageMenuItem.Click += RightClickMenu_Copy_Click; cm.Items.Add(CopyImageMenuItem); MenuItem AutoAxisMenuItem = new() { Header = "自适应数据" }; AutoAxisMenuItem.Click += RightClickMenu_AutoAxis_Click; cm.Items.Add(AutoAxisMenuItem); cm.IsOpen = true; } #region 右键菜单 private void RightClickMenu_Copy_Click(object sender, EventArgs e) => System.Windows.Clipboard.SetImage(BmpImageFromBmp(plt.Plot.Render())); // private void RightClickMenu_Help_Click(object sender, EventArgs e) => new WPF.HelpWindow().Show(); // private void RightClickMenu_OpenInNewWindow_Click(object sender, EventArgs e) => new WpfPlotViewer(plt.Plot).Show(); private void RightClickMenu_AutoAxis_Click(object sender, EventArgs e) { plt.Plot.AxisAuto(); plt.Refresh(); } private void RightClickMenu_SaveImage_Click(object sender, EventArgs e) { var sfd = new SaveFileDialog { FileName = "ScottPlot.png", Filter = "PNG Files (*.png)|*.png;*.png" + "|JPG Files (*.jpg, *.jpeg)|*.jpg;*.jpeg" + "|BMP Files (*.bmp)|*.bmp;*.bmp" + "|All files (*.*)|*.*" }; if (sfd.ShowDialog() is true) plt.Plot.SaveFig(sfd.FileName); } private static BitmapImage BmpImageFromBmp(System.Drawing.Bitmap bmp) { using var memory = new System.IO.MemoryStream(); bmp.Save(memory, System.Drawing.Imaging.ImageFormat.Png); memory.Position = 0; var bitmapImage = new BitmapImage(); bitmapImage.BeginInit(); bitmapImage.StreamSource = memory; bitmapImage.CacheOption = BitmapCacheOption.OnLoad; bitmapImage.EndInit(); bitmapImage.Freeze(); return bitmapImage; } #endregion } }