using MathNet.Numerics;
using MathNet.Numerics.Interpolation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Drawing;
using ScottPlot;
using ScottPlot.WinForms;
namespace ResamplerLib
{
public static class ResamplerMgr
{
public static void Resample(int sampleCount, List<double> x, List<double> y, out List<double> xout, out List<double> yout)
{
xout = new List<double>();
yout = new List<double>();
if (!ValidateInput(x, y, sampleCount)) return;
try
{
IInterpolation ip = Interpolate.CubicSpline(x.ToArray(), y.ToArray());
double start = x[0];
double stop = x[x.Count - 1];
if (sampleCount == 1 || Math.Abs(stop - start) < 1e-10)
{
xout.Add(start);
yout.Add(y[0]);
return;
}
double step = (stop - start) / (sampleCount - 1);
for (double sx = start; sx <= stop + 1e-10; sx += step)
{
double sy = ip.Interpolate(sx);
if (double.IsNaN(sy) || double.IsInfinity(sy))
{
sy = sx <= x[0] ? y[0] : y[y.Count - 1];
Console.WriteLine($"警告:sx={sx:F3} 处插值异常,使用边界值 {sy:F3}");
}
xout.Add(sx);
yout.Add(sy);
}
}
catch (Exception ex)
{
Console.WriteLine($"重采样失败:{ex.Message}");
xout = new List<double>(x);
yout = new List<double>(y);
}
}
public static void Resample(int sampleCount, List<double> x, List<double> y, List<double> xx, out List<double> yy)
{
yy = new List<double>();
if (!ValidateInput(x, y, 1) || xx == null || xx.Count == 0)
{
Console.WriteLine("无效输入:xx 必须非空且有效");
return;
}
try
{
IInterpolation ip = Interpolate.CubicSpline(x.ToArray(), y.ToArray());
foreach (double sx in xx)
{
double sy = ip.Interpolate(sx);
if (double.IsNaN(sy) || double.IsInfinity(sy))
{
sy = sx <= x[0] ? y[0] : y[y.Count - 1];
Console.WriteLine($"警告:sx={sx:F3} 处插值异常,使用边界值 {sy:F3}");
}
yy.Add(sy);
}
}
catch (Exception ex)
{
Console.WriteLine($"重采样失败:{ex.Message}");
}
}
public static void Resample2(int sampleCount, List<double> x, List<double> y, out List<double> xout, out List<double> yout)
{
xout = new List<double>();
yout = new List<double>();
Resample(2 * sampleCount, x, y, out List<double> xTemp, out List<double> yTemp);
List<double> x2 = new List<double>(x);
List<double> y2 = new List<double>(y);
x2.AddRange(xTemp);
y2.AddRange(yTemp);
Resample(sampleCount, x2, y2, out xout, out yout);
}
private static bool ValidateInput(List<double> x, List<double> y, int sampleCount)
{
if (x == null || y == null || x.Count != y.Count || x.Count < 2 || sampleCount <= 0)
{
Console.WriteLine("无效输入:x 和 y 必须非空、长度相等、至少 2 个点,且 sampleCount > 0");
return false;
}
if (x.Any(double.IsNaN) || y.Any(double.IsNaN) || x.Any(double.IsInfinity) || y.Any(double.IsInfinity))
{
Console.WriteLine("无效输入:x 和 y 不能包含 NaN 或 Infinity");
return false;
}
for (int i = 1; i < x.Count; i++)
{
if (x[i] <= x[i - 1])
{
Console.WriteLine("无效输入:x 必须严格递增");
return false;
}
}
return true;
}
}
class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var form = new Form { Text = "电压曲线展示 - ScottPlot 5.0.55", Width = 800, Height = 600 };
var formsPlot = new FormsPlot { Dock = DockStyle.Fill };
form.Controls.Add(formsPlot);
List<double> x = new List<double>();
List<double> y = new List<double>();
Random rand = new Random(42);
for (double t = -5.0; t <= 5.0; t += 0.5)
{
x.Add(t);
double voltage = 5.0 * Math.Sin(t) + (rand.NextDouble() - 0.5) * 0.5;
y.Add(voltage);
}
int sampleCount = 100;
ResamplerMgr.Resample(sampleCount, x, y, out List<double> xout, out List<double> yout);
var plt = formsPlot.Plot;
var scatterOriginal = plt.Add.Scatter(x.ToArray(), y.ToArray(), color: Colors.Blue);
scatterOriginal.MarkerStyle.Size = 5;
scatterOriginal.Label = "原始数据";
var scatterResampled = plt.Add.Scatter(xout.ToArray(), yout.ToArray(), color: Colors.Red);
scatterResampled.MarkerStyle.Size = 0;
scatterResampled.LineStyle.Width = 2;
scatterResampled.Label = "重采样数据";
plt.Title("电压曲线(原始 vs 重采样)", size: 14);
plt.Axes.Bottom.Label.Text = "时间 (秒)";
plt.Axes.Left.Label.Text = "电压 (伏特)";
plt.Legend.IsVisible = true;
plt.Legend.Alignment = Alignment.UpperRight;
plt.Axes.AutoScale();
formsPlot.MouseMove += (s, e) =>
{
var pixel = new Pixel(e.Location.X, e.Location.Y);
var coords = formsPlot.Plot.GetCoordinates(pixel);
form.Text = $"电压曲线展示 - 时间:{coords.X:F3} 秒,电压:{coords.Y:F3} 伏特";
};
try
{
plt.Save("voltage_curve_scottplot.png", 800, 600, ImageFormat.Png);
Console.WriteLine("图像已保存为 voltage_curve_scottplot.png");
}
catch (Exception ex)
{
Console.WriteLine($"保存图像失败:{ex.Message}");
}
formsPlot.Refresh();
Application.Run(form);
}
}
}