Files
2024-11-26 20:15:16 +09:00

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