|
|
|
|
namespace Connected.Components;
|
|
|
|
|
|
|
|
|
|
public abstract class SplineInterpolator : ILineInterpolator
|
|
|
|
|
{
|
|
|
|
|
protected Matrix m;
|
|
|
|
|
protected MatrixSolver gauss;
|
|
|
|
|
|
|
|
|
|
protected readonly int n;
|
|
|
|
|
protected double[] a, b, c, d, h;
|
|
|
|
|
|
|
|
|
|
public double[] GivenYs { get; set; }
|
|
|
|
|
public double[] GivenXs { get; set; }
|
|
|
|
|
public double[] InterpolatedXs { get; set; }
|
|
|
|
|
public double[] InterpolatedYs { get; set; }
|
|
|
|
|
public bool InterpolationRequired { get; set; } = true;
|
|
|
|
|
|
|
|
|
|
public SplineInterpolator(double[] xs, double[] ys, int resolution = 10)
|
|
|
|
|
{
|
|
|
|
|
if (xs is null || ys is null)
|
|
|
|
|
throw new ArgumentException("xs and ys cannot be null");
|
|
|
|
|
|
|
|
|
|
if (xs.Length != ys.Length)
|
|
|
|
|
throw new ArgumentException("xs and ys must have the same length");
|
|
|
|
|
|
|
|
|
|
if (xs.Length < 4)
|
|
|
|
|
throw new ArgumentException("xs and ys must have a length of 4 or greater");
|
|
|
|
|
|
|
|
|
|
if (resolution < 1)
|
|
|
|
|
throw new ArgumentException("resolution must be 1 or greater");
|
|
|
|
|
|
|
|
|
|
GivenXs = xs;
|
|
|
|
|
GivenYs = ys;
|
|
|
|
|
n = xs.Length;
|
|
|
|
|
|
|
|
|
|
InterpolatedXs = new double[n * resolution];
|
|
|
|
|
InterpolatedYs = new double[n * resolution];
|
|
|
|
|
}
|
|
|
|
|
public void Interpolate()
|
|
|
|
|
{
|
|
|
|
|
int resolution = InterpolatedXs.Length / n;
|
|
|
|
|
for (int i = 0; i < h.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
for (int k = 0; k < resolution; k++)
|
|
|
|
|
{
|
|
|
|
|
double deltaX = (double)k / resolution * h[i];
|
|
|
|
|
double termA = a[i];
|
|
|
|
|
double termB = b[i] * deltaX;
|
|
|
|
|
double termC = c[i] * deltaX * deltaX;
|
|
|
|
|
double termD = d[i] * deltaX * deltaX * deltaX;
|
|
|
|
|
int interpolatedIndex = i * resolution + k;
|
|
|
|
|
InterpolatedXs[interpolatedIndex] = deltaX + GivenXs[i];
|
|
|
|
|
InterpolatedYs[interpolatedIndex] = termA + termB + termC + termD;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// After interpolation the last several values of the interpolated arrays
|
|
|
|
|
// contain uninitialized data. This section identifies the values which are
|
|
|
|
|
// populated with values and copies just the useful data into new arrays.
|
|
|
|
|
int pointsToKeep = resolution * (n - 1) + 1;
|
|
|
|
|
double[] interpolatedXsCopy = new double[pointsToKeep];
|
|
|
|
|
double[] interpolatedYsCopy = new double[pointsToKeep];
|
|
|
|
|
Array.Copy(InterpolatedXs, 0, interpolatedXsCopy, 0, pointsToKeep - 1);
|
|
|
|
|
Array.Copy(InterpolatedYs, 0, interpolatedYsCopy, 0, pointsToKeep - 1);
|
|
|
|
|
InterpolatedXs = interpolatedXsCopy;
|
|
|
|
|
InterpolatedYs = interpolatedYsCopy;
|
|
|
|
|
InterpolatedXs[pointsToKeep - 1] = GivenXs[n - 1];
|
|
|
|
|
InterpolatedYs[pointsToKeep - 1] = GivenYs[n - 1];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public double Integrate()
|
|
|
|
|
{
|
|
|
|
|
double integral = 0;
|
|
|
|
|
for (int i = 0; i < h.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
double termA = a[i] * h[i];
|
|
|
|
|
double termB = b[i] * Math.Pow(h[i], 2) / 2.0;
|
|
|
|
|
double termC = c[i] * Math.Pow(h[i], 3) / 3.0;
|
|
|
|
|
double termD = d[i] * Math.Pow(h[i], 4) / 4.0;
|
|
|
|
|
integral += termA + termB + termC + termD;
|
|
|
|
|
}
|
|
|
|
|
return integral;
|
|
|
|
|
}
|
|
|
|
|
}
|