using System;
namespace Legalsoft.Truffer
{
///
/// 二维三次样条插值
/// Object for two-dimensional cubic spline interpolation on a matrix.Construct
/// with a vector of x1 values, a vector of x2 values, and a matrix of tabulated
/// function values yij.Then call interp for interpolated values.
///
public class Spline2D_interp
{
private int[,] bcucof_wt = new int[,] {
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ -3, 0, 0, 3, 0, 0, 0, 0, -2, 0, 0, -1, 0, 0, 0, 0 },
{ 2, 0, 0, -2, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 },
{ 0, 0, 0, 0, -3, 0, 0, 3, 0, 0, 0, 0, -2, 0, 0, -1 },
{ 0, 0, 0, 0, 2, 0, 0, -2, 0, 0, 0, 0, 1, 0, 0, 1 },
{ -3, 3, 0, 0, -2, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, -3, 3, 0, 0, -2, -1, 0, 0 },
{ 9, -9, 9, -9, 6, 3, -3, -6, 6, -6, -3, 3, 4, 2, 1, 2 },
{ -6, 6, -6, 6, -4, -2, 2, 4, -3, 3, 3, -3, -2, -1, -1, -2 },
{ 2, -2, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 2, -2, 0, 0, 1, 1, 0, 0 },
{ -6, 6, -6, 6, -3, -3, 3, 3, -4, 4, 2, -2, -2, -2, -1, -1 },
{ 4, -4, 4, -4, 2, 2, -2, -2, 2, -2, -2, 2, 1, 1, 1, 1 }
};
private int m { get; set; }
private int n { get; set; }
private double[,] y { get; set; }
private double[] x1 { get; set; }
private double[] yv { get; set; }
private Spline_interp[] srp { get; set; }
public Spline2D_interp(double[] x1v, double[] x2v, double[,] ym)
{
this.m = x1v.Length;
this.n = x2v.Length;
this.y = ym;
this.yv = new double[m];
this.x1 = x1v;
this.srp = new Spline_interp[m];
for (int i = 0; i < m; i++)
{
srp[i] = new Spline_interp(x2v, y[i, 0]);
}
}
public double interp(double x1p, double x2p)
{
for (int i = 0; i < m; i++)
{
yv[i] = (srp[i]).interp(x2p);
}
Spline_interp scol = new Spline_interp(x1, yv);
return scol.interp(x1p);
}
///
/// Given arrays y[0..3], y1[0..3], y2[0..3], and y12[0..3], containing the
/// function, gradients, and cross-derivative at the four grid points of a
/// rectangular grid cell(numbered counterclockwise from the lower left), and
/// given d1 and d2, the length of the grid cell in the 1 and 2 directions,
/// this routine returns the table c[0..3][0..3] that is used by routine bcuint
/// for bicubic interpolation.
///
///
///
///
///
///
///
///
private void bcucof(double[] y, double[] y1, double[] y2, double[] y12, double d1, double d2, double[,] c)
{
//int[,] bcucof_wt = new int[16, 16]{ bcucof_wt_d };
double d1d2 = d1 * d2;
double[] cl = new double[16];
double[] x = new double[16];
for (int i = 0; i < 4; i++)
{
x[i] = y[i];
x[i + 4] = y1[i] * d1;
x[i + 8] = y2[i] * d2;
x[i + 12] = y12[i] * d1d2;
}
for (int i = 0; i < 16; i++)
{
double xx = 0.0;
for (int k = 0; k < 16; k++)
{
xx += bcucof_wt[i, k] * x[k];
}
cl[i] = xx;
}
int l = 0;
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
c[i, j] = cl[l++];
}
}
}
///
/// Bicubic interpolation within a grid square.Input quantities are
/// y, y1, y2, y12 (as described in bcucof); x1l and x1u, the lower and upper
/// coordinates of the grid square in the 1 direction; x2l and x2u likewise for
/// the 2 direction; and x1, x2, the coordinates of the desired point for the
/// interpolation.The interpolated function value is returned as ansy, and the
/// interpolated gradient values as ansy1 and ansy2.This routine calls bcucof.
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
public void bcuint(double[] y, double[] y1, double[] y2, double[] y12, double x1l, double x1u, double x2l, double x2u, double x1, double x2, ref double ansy, ref double ansy1, ref double ansy2)
{
double d1 = x1u - x1l;
double d2 = x2u - x2l;
double[,] c = new double[4, 4];
bcucof(y, y1, y2, y12, d1, d2, c);
//if (x1u == x1l || x2u == x2l)
if (Math.Abs(x1u - x1l) <= float.Epsilon || Math.Abs(x2u - x2l) <= float.Epsilon)
{
throw new Exception("Bad input in routine bcuint");
}
double t = (x1 - x1l) / d1;
double u = (x2 - x2l) / d2;
ansy = ansy2 = ansy1 = 0.0;
for (int i = 3; i >= 0; i--)
{
ansy = t * ansy + ((c[i, 3] * u + c[i, 2]) * u + c[i, 1]) * u + c[i, 0];
ansy2 = t * ansy2 + (3.0 * c[i, 3] * u + 2.0 * c[i, 2]) * u + c[i, 1];
ansy1 = u * ansy1 + (3.0 * c[3, i] * t + 2.0 * c[2, i]) * t + c[1, i];
}
ansy1 /= d1;
ansy2 /= d2;
}
}
}
using System;
namespace Legalsoft.Truffer
{
///
/// 二维三次样条插值
/// Object for two-dimensional cubic spline interpolation on a matrix.Construct
/// with a vector of x1 values, a vector of x2 values, and a matrix of tabulated
/// function values yij.Then call interp for interpolated values.
///
public class Spline2D_interp
{
private int[,] bcucof_wt = new int[,] {
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ -3, 0, 0, 3, 0, 0, 0, 0, -2, 0, 0, -1, 0, 0, 0, 0 },
{ 2, 0, 0, -2, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 },
{ 0, 0, 0, 0, -3, 0, 0, 3, 0, 0, 0, 0, -2, 0, 0, -1 },
{ 0, 0, 0, 0, 2, 0, 0, -2, 0, 0, 0, 0, 1, 0, 0, 1 },
{ -3, 3, 0, 0, -2, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, -3, 3, 0, 0, -2, -1, 0, 0 },
{ 9, -9, 9, -9, 6, 3, -3, -6, 6, -6, -3, 3, 4, 2, 1, 2 },
{ -6, 6, -6, 6, -4, -2, 2, 4, -3, 3, 3, -3, -2, -1, -1, -2 },
{ 2, -2, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 2, -2, 0, 0, 1, 1, 0, 0 },
{ -6, 6, -6, 6, -3, -3, 3, 3, -4, 4, 2, -2, -2, -2, -1, -1 },
{ 4, -4, 4, -4, 2, 2, -2, -2, 2, -2, -2, 2, 1, 1, 1, 1 }
};
private int m { get; set; }
private int n { get; set; }
private double[,] y { get; set; }
private double[] x1 { get; set; }
private double[] yv { get; set; }
private Spline_interp[] srp { get; set; }
public Spline2D_interp(double[] x1v, double[] x2v, double[,] ym)
{
this.m = x1v.Length;
this.n = x2v.Length;
this.y = ym;
this.yv = new double[m];
this.x1 = x1v;
this.srp = new Spline_interp[m];
for (int i = 0; i < m; i++)
{
srp[i] = new Spline_interp(x2v, y[i, 0]);
}
}
public double interp(double x1p, double x2p)
{
for (int i = 0; i < m; i++)
{
yv[i] = (srp[i]).interp(x2p);
}
Spline_interp scol = new Spline_interp(x1, yv);
return scol.interp(x1p);
}
///
/// Given arrays y[0..3], y1[0..3], y2[0..3], and y12[0..3], containing the
/// function, gradients, and cross-derivative at the four grid points of a
/// rectangular grid cell(numbered counterclockwise from the lower left), and
/// given d1 and d2, the length of the grid cell in the 1 and 2 directions,
/// this routine returns the table c[0..3][0..3] that is used by routine bcuint
/// for bicubic interpolation.
///
///
///
///
///
///
///
///
private void bcucof(double[] y, double[] y1, double[] y2, double[] y12, double d1, double d2, double[,] c)
{
//int[,] bcucof_wt = new int[16, 16]{ bcucof_wt_d };
double d1d2 = d1 * d2;
double[] cl = new double[16];
double[] x = new double[16];
for (int i = 0; i < 4; i++)
{
x[i] = y[i];
x[i + 4] = y1[i] * d1;
x[i + 8] = y2[i] * d2;
x[i + 12] = y12[i] * d1d2;
}
for (int i = 0; i < 16; i++)
{
double xx = 0.0;
for (int k = 0; k < 16; k++)
{
xx += bcucof_wt[i, k] * x[k];
}
cl[i] = xx;
}
int l = 0;
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
c[i, j] = cl[l++];
}
}
}
///
/// Bicubic interpolation within a grid square.Input quantities are
/// y, y1, y2, y12 (as described in bcucof); x1l and x1u, the lower and upper
/// coordinates of the grid square in the 1 direction; x2l and x2u likewise for
/// the 2 direction; and x1, x2, the coordinates of the desired point for the
/// interpolation.The interpolated function value is returned as ansy, and the
/// interpolated gradient values as ansy1 and ansy2.This routine calls bcucof.
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
public void bcuint(double[] y, double[] y1, double[] y2, double[] y12, double x1l, double x1u, double x2l, double x2u, double x1, double x2, ref double ansy, ref double ansy1, ref double ansy2)
{
double d1 = x1u - x1l;
double d2 = x2u - x2l;
double[,] c = new double[4, 4];
bcucof(y, y1, y2, y12, d1, d2, c);
//if (x1u == x1l || x2u == x2l)
if (Math.Abs(x1u - x1l) <= float.Epsilon || Math.Abs(x2u - x2l) <= float.Epsilon)
{
throw new Exception("Bad input in routine bcuint");
}
double t = (x1 - x1l) / d1;
double u = (x2 - x2l) / d2;
ansy = ansy2 = ansy1 = 0.0;
for (int i = 3; i >= 0; i--)
{
ansy = t * ansy + ((c[i, 3] * u + c[i, 2]) * u + c[i, 1]) * u + c[i, 0];
ansy2 = t * ansy2 + (3.0 * c[i, 3] * u + 2.0 * c[i, 2]) * u + c[i, 1];
ansy1 = u * ansy1 + (3.0 * c[3, i] * t + 2.0 * c[2, i]) * t + c[1, i];
}
ansy1 /= d1;
ansy2 /= d2;
}
}
}