268 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			268 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| 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<AxisLine>().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();
 | |
|         }
 | |
|     }
 | |
| }
 | 
