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();
|
|
}
|
|
}
|
|
}
|