using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using ScottPlot; using ScottPlot.Plottables; using ScottPlot.TickGenerators; using ScottPlot.WinForms; namespace chart_scottplot { public partial class Form1 : Form { // Create an instance of a FormsPlot like this readonly FormsPlot formsPlot1; public Form1() { InitializeComponent(); // Add the FormsPlot to the panel formsPlot1 = new FormsPlot() { Dock = DockStyle.Fill }; panel1.Controls.Add(formsPlot1); } ScottPlot.Plottables.Crosshair CrossHair; private DateTime[] xs,xs2; private double[] ys,ys2; private int pointCount; private void Form1_Load(object sender, EventArgs e) { // 초기 데이터 생성 pointCount = 51; xs = new DateTime[pointCount]; ys = new double[pointCount]; xs2 = new DateTime[pointCount]; ys2 = new double[pointCount]; DateTime startTime = DateTime.Now; for (int i = 0; i < pointCount; i++) { xs[i] = startTime.AddSeconds(i); ys[i] = Math.Sin(i * 0.1); xs2[i] = startTime.AddSeconds(i); ys2[i] = Math.Sin(i * 0.1)+0.1; } // 초기 데이터 플로팅 var sig3 = formsPlot1.Plot.Add.Scatter(xs, ys); // formsPlot1.Plot.Axes.DateTimeTicksBottom(); var sig4 = formsPlot1.Plot.Add.Scatter(xs2, ys2); formsPlot1.Plot.Axes.DateTimeTicksBottom(); //var sig1 = formsPlot1.Plot.Add.Signal(Generate.Sin(51)); //sig1.LegendText = "Sin"; //var sig2 = formsPlot1.Plot.Add.Signal(Generate.Cos(51)); //sig2.LegendText = "Sin"; //myScatter.Color = Colors.Green.WithOpacity(.2); //myScatter.LineWidth = 5; //myScatter.MarkerSize = 15; //formsPlot1.Plot.Axes.SetLimits(-100, 150, -5, 5); //limit 설정 formsPlot1.Plot.Axes.AutoScale(); //auto limit , fit data formsPlot1.Plot.XLabel("TIME"); formsPlot1.Plot.YLabel("VOLTAGE"); //formsPlot1.Plot.Title("V"); var anno = formsPlot1.Plot.Add.Annotation("This is an Annotation"); anno.LabelFontSize = 32; anno.LabelFontName = Fonts.Serif; anno.LabelBackgroundColor = Colors.RebeccaPurple.WithAlpha(.3); anno.LabelFontColor = Colors.RebeccaPurple; anno.LabelBorderColor = Colors.Green; anno.LabelBorderWidth = 3; anno.LabelShadowColor = Colors.Transparent; anno.OffsetY = 40; anno.OffsetX = 20; CrossHair = formsPlot1.Plot.Add.Crosshair(0, 0); CrossHair.TextColor = Colors.White; CrossHair.TextBackgroundColor = CrossHair.HorizontalLine.Color; //커서기능용 특정위치에 세로선을 표시 var axLine1 = formsPlot1.Plot.Add.VerticalLine(startTime.AddSeconds(pointCount / 2).ToOADate()); axLine1.Text = "Cursor 1"; axLine1.LabelAlignment = Alignment.UpperRight; axLine1.IsDraggable = true; var axLine2 = formsPlot1.Plot.Add.VerticalLine(startTime.AddSeconds(pointCount / 3).ToOADate()); axLine2.Text = "Cursor 2"; axLine2.LabelAlignment = Alignment.UpperRight; axLine2.IsDraggable = true; var hs = formsPlot1.Plot.Add.HorizontalSpan(startTime.AddSeconds(pointCount / 4).ToOADate(), startTime.AddSeconds(pointCount / 3).ToOADate()); hs.LegendText = "Hello"; hs.LineStyle.Width = 2; hs.LineStyle.Color = Colors.Magenta; hs.LineStyle.Pattern = LinePattern.Dashed; hs.FillStyle.Color = Colors.Magenta.WithAlpha(.2); formsPlot1.Plot.Add.Callout("Hello", textLocation: new Coordinates(xs[5].ToOADate(), 0.3), tipLocation: new Coordinates(xs[6].ToOADate(), 1.2)); //double[] values = { 100, 80}; //formsPlot1.Plot.Add.RadialGaugePlot(values); // add logic into the RenderStarting event to customize tick labels formsPlot1.Plot.RenderManager.RenderStarting += (s1, e1) => { Tick[] ticks = formsPlot1.Plot.Axes.Bottom.TickGenerator.Ticks; for (int i = 0; i < ticks.Length; i++) { DateTime dt = DateTime.FromOADate(ticks[i].Position); string label = $"{dt:HH}:{dt:mm}:{dt:ss}"; ticks[i] = new Tick(ticks[i].Position, label); } }; // some items must be styled directly //formsPlot1.Plot.Grid.MajorLineColor = Color.FromHex("#0e3d54"); //formsPlot1.Plot.FigureBackground.Color = Color.FromHex("#07263b"); //formsPlot1.Plot.DataBackground.Color = Color.FromHex("#0b3049"); // create a custom formatter to return a string with // date only when zoomed out and time only when zoomed in // apply our custom tick formatter // the Style object contains helper methods to style many items at once formsPlot1.Plot.Axes.Color(Color.FromHex("#a0acb5")); formsPlot1.MouseDown += FormsPlot1_MouseDown; formsPlot1.MouseUp += FormsPlot1_MouseUp; formsPlot1.MouseMove += FormsPlot1_MouseMove; formsPlot1.Refresh(); } private void FormsPlot1_MouseDown(object sender, MouseEventArgs e) { var lineUnderMouse = GetLineUnderMouse(e.X, e.Y); if (lineUnderMouse != null) { PlottableBeingDragged = lineUnderMouse; formsPlot1.Interaction.Disable(); // disable panning while dragging } } private void FormsPlot1_MouseUp(object sender, MouseEventArgs e) { PlottableBeingDragged = null; formsPlot1.Interaction.Enable(); // enable panning again formsPlot1.Refresh(); } AxisLine PlottableBeingDragged = null; private void FormsPlot1_MouseMove(object sender, MouseEventArgs e) { //update cross line Pixel mousePixel = new Pixel(e.X, e.Y); Coordinates mouseCoordinates = formsPlot1.Plot.GetCoordinates(mousePixel); this.Text = $"X={mouseCoordinates.X:N3}, Y={mouseCoordinates.Y:N3}"; CrossHair.Position = mouseCoordinates; CrossHair.VerticalLine.Text = $"{mouseCoordinates.X:N3}"; CrossHair.HorizontalLine.Text = $"{mouseCoordinates.Y:N3}"; formsPlot1.Refresh(); // this rectangle is the area around the mouse in coordinate units CoordinateRect rect = formsPlot1.Plot.GetCoordinateRect(e.X, e.Y, radius: 10); if (PlottableBeingDragged is null) { // set cursor based on what's beneath the plottable var lineUnderMouse = GetLineUnderMouse(e.X, e.Y); if (lineUnderMouse is null) Cursor = Cursors.Default; else if (lineUnderMouse.IsDraggable && lineUnderMouse is VerticalLine) Cursor = Cursors.SizeWE; else if (lineUnderMouse.IsDraggable && lineUnderMouse is HorizontalLine) Cursor = Cursors.SizeNS; } else { // update the position of the plottable being dragged if (PlottableBeingDragged is HorizontalLine hl) { hl.Y = rect.VerticalCenter; hl.Text = $"{hl.Y:0.00}"; } else if (PlottableBeingDragged is VerticalLine vl) { vl.X = rect.HorizontalCenter; vl.Text = $"{vl.X:0.00}"; } formsPlot1.Refresh(); } } private AxisLine GetLineUnderMouse(float x, float y) { CoordinateRect rect = formsPlot1.Plot.GetCoordinateRect(x, y, radius: 10); foreach (AxisLine axLine in formsPlot1.Plot.GetPlottables().Reverse()) { if (axLine.IsUnderMouse(rect)) return axLine; } return null; } private void button1_Click(object sender, EventArgs e) { } private void button2_Click(object sender, EventArgs e) { AddDataPoint(); } public void AddDataPoint() { // 새로운 데이터 추가 pointCount += 1; Array.Resize(ref xs, pointCount); Array.Resize(ref ys, pointCount); xs[pointCount - 1] = xs[pointCount - 2].AddSeconds(1); ys[pointCount - 1] = Math.Sin(pointCount * 0.1); // 데이터 업데이트 formsPlot1.Plot.Clear(); formsPlot1.Plot.Add.Scatter(xs, ys); // Y축 자동 스케일 조정 //FormsPlot1.Plot.Axes.AutoScaleY(); formsPlot1.Plot.Axes.AutoScale(); // 플롯 갱신 formsPlot1.Refresh(); } } }