Init( IList <double> t, IList <double> x ) { if (null == t) { throw new ArgumentNullException("t"); } if (null == x) { throw new ArgumentNullException("x"); } if (t.Count < 5) { throw new ArgumentOutOfRangeException("t"); } if (t.Count != x.Count) { throw new ArgumentException(Properties.Resources.ArgumentVectorsSameLengths, "x"); } int n = t.Count; double[] tt = new double[n]; t.CopyTo(tt, 0); double[] xx = new double[n]; x.CopyTo(xx, 0); Sorting.Sort(tt, xx); // Prepare W (weights), Diff (divided differences) double[] w = new double[n - 1]; double[] diff = new double[n - 1]; for (int i = 0; i < diff.Length; i++) { diff[i] = (xx[i + 1] - xx[i]) / (tt[i + 1] - tt[i]); } for (int i = 1; i < w.Length; i++) { w[i] = Math.Abs(diff[i] - diff[i - 1]); } // Prepare Hermite interpolation scheme double[] d = new double[n]; for (int i = 2; i < d.Length - 2; i++) { if (!Number.AlmostZero(w[i - 1]) || !Number.AlmostZero(w[i + 1])) { d[i] = (w[i + 1] * diff[i - 1] + w[i - 1] * diff[i]) / (w[i + 1] + w[i - 1]); } else { d[i] = ((tt[i + 1] - tt[i]) * diff[i - 1] + (tt[i] - tt[i - 1]) * diff[i]) / (tt[i + 1] - tt[i - 1]); } } d[0] = DifferentiateThreePoint(tt[0], tt[0], xx[0], tt[1], xx[1], tt[2], xx[2]); d[1] = DifferentiateThreePoint(tt[1], tt[0], xx[0], tt[1], xx[1], tt[2], xx[2]); d[n - 2] = DifferentiateThreePoint(tt[n - 2], tt[n - 3], xx[n - 3], tt[n - 2], xx[n - 2], tt[n - 1], xx[n - 1]); d[n - 1] = DifferentiateThreePoint(tt[n - 1], tt[n - 3], xx[n - 3], tt[n - 2], xx[n - 2], tt[n - 1], xx[n - 1]); // Build Akima spline using Hermite interpolation scheme _hermiteSpline.InitInternal(tt, xx, d); }
Init( IList <double> t, IList <double> x, SplineBoundaryCondition leftBoundaryCondition, double leftBoundary, SplineBoundaryCondition rightBoundaryCondition, double rightBoundary ) { if (null == t) { throw new ArgumentNullException("t"); } if (null == x) { throw new ArgumentNullException("x"); } if (t.Count < 2) { throw new ArgumentOutOfRangeException("t"); } if (t.Count != x.Count) { throw new ArgumentException(Properties.Resources.ArgumentVectorsSameLengths, "x"); } int n = t.Count; double[] tt = new double[n]; t.CopyTo(tt, 0); double[] xx = new double[n]; x.CopyTo(xx, 0); Sorting.Sort(tt, xx); // normalize special cases if ((n == 2) && (leftBoundaryCondition == SplineBoundaryCondition.ParabolicallyTerminated) && (rightBoundaryCondition == SplineBoundaryCondition.ParabolicallyTerminated)) { leftBoundaryCondition = SplineBoundaryCondition.SecondDerivative; leftBoundary = 0d; rightBoundaryCondition = SplineBoundaryCondition.SecondDerivative; rightBoundary = 0d; } if (leftBoundaryCondition == SplineBoundaryCondition.Natural) { leftBoundaryCondition = SplineBoundaryCondition.SecondDerivative; leftBoundary = 0d; } if (rightBoundaryCondition == SplineBoundaryCondition.Natural) { rightBoundaryCondition = SplineBoundaryCondition.SecondDerivative; rightBoundary = 0d; } double[] a1 = new double[n]; double[] a2 = new double[n]; double[] a3 = new double[n]; double[] b = new double[n]; // Left Boundary switch (leftBoundaryCondition) { case SplineBoundaryCondition.ParabolicallyTerminated: a1[0] = 0; a2[0] = 1; a3[0] = 1; b[0] = 2 * (xx[1] - xx[0]) / (tt[1] - tt[0]); break; case SplineBoundaryCondition.FirstDerivative: a1[0] = 0; a2[0] = 1; a3[0] = 0; b[0] = leftBoundary; break; case SplineBoundaryCondition.SecondDerivative: a1[0] = 0; a2[0] = 2; a3[0] = 1; b[0] = 3 * (xx[1] - xx[0]) / (tt[1] - tt[0]) - 0.5 * leftBoundary * (tt[1] - tt[0]); break; default: throw new NotSupportedException(Properties.Resources.InvalidLeftBoundaryCondition); } // Central Conditions for (int i = 1; i < tt.Length - 1; i++) { a1[i] = tt[i + 1] - tt[i]; a2[i] = 2 * (tt[i + 1] - tt[i - 1]); a3[i] = tt[i] - tt[i - 1]; b[i] = 3 * (xx[i] - xx[i - 1]) / (tt[i] - tt[i - 1]) * (tt[i + 1] - tt[i]) + 3 * (xx[i + 1] - xx[i]) / (tt[i + 1] - tt[i]) * (tt[i] - tt[i - 1]); } // Right Boundary switch (rightBoundaryCondition) { case SplineBoundaryCondition.ParabolicallyTerminated: a1[n - 1] = 1; a2[n - 1] = 1; a3[n - 1] = 0; b[n - 1] = 2 * (xx[n - 1] - xx[n - 2]) / (tt[n - 1] - tt[n - 2]); break; case SplineBoundaryCondition.FirstDerivative: a1[n - 1] = 0; a2[n - 1] = 1; a3[n - 1] = 0; b[n - 1] = rightBoundary; break; case SplineBoundaryCondition.SecondDerivative: a1[n - 1] = 1; a2[n - 1] = 2; a3[n - 1] = 0; b[n - 1] = 3 * (xx[n - 1] - xx[n - 2]) / (tt[n - 1] - tt[n - 2]) + 0.5 * rightBoundary * (tt[n - 1] - tt[n - 2]); break; default: throw new NotSupportedException(Properties.Resources.InvalidRightBoundaryCondition); } // Build Spline double[] dd = SolveTridiagonal(a1, a2, a3, b); _hermiteSpline.InitInternal(tt, xx, dd); }