You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

208 lines
7.8 KiB
C#

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
{
/// <summary>
/// ChartPlot.xaml 的交互逻辑
/// </summary>
public partial class ChartPlotView : UserControl
{
public DispatcherTimer _renderTimer = new DispatcherTimer();
//非定时更新需停止定时器
List<SignalPlot> scatterPlots = new List<SignalPlot>();
//每天生成的最大点数*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<string> lineLabels;
lineLabels = new List<string>();
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<double[]> 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> 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
}
}