/// <summary> /// Evaluation of complete interpolating function. Note that since each curve /// segment is controlled by four points, the end points will not be /// interpolated. If extra control points are not desirable, the end points /// can simply be repeated to ensure interpolation. Note also that points of /// non-differentiability and discontinuity can be introduced by repeating /// points /// </summary> /// <param name="f0_base"></param> /// <param name="p0"></param> /// <param name="pn"></param> /// <param name="plotter"></param> /// <param name="res"></param> public void interpolate(int[][] f0_base, int p0, int pn, PointPlotter plotter, double res) { double k1, k2; // Set up points for first curve segment. int p1 = p0; ++p1; int p2 = p1; ++p2; int p3 = p2; ++p3; // Draw each curve segment. for (; p2 != pn; ++p0, ++p1, ++p2, ++p3) { // p1 and p2 equal; single point. if (x(f0_base, p1) == x(f0_base, p2)) { continue; } // Both end points repeated; straight line. if (x(f0_base, p0) == x(f0_base, p1) && x(f0_base, p2) == x(f0_base, p3)) { k1 = k2 = (y(f0_base, p2) - y(f0_base, p1)) / (x(f0_base, p2) - x(f0_base, p1)); } // p0 and p1 equal; use f''(x1) = 0. else if (x(f0_base, p0) == x(f0_base, p1)) { k2 = (y(f0_base, p3) - y(f0_base, p1)) / (x(f0_base, p3) - x(f0_base, p1)); k1 = (3 * (y(f0_base, p2) - y(f0_base, p1)) / (x(f0_base, p2) - x(f0_base, p1)) - k2) / 2; } // p2 and p3 equal; use f''(x2) = 0. else if (x(f0_base, p2) == x(f0_base, p3)) { k1 = (y(f0_base, p2) - y(f0_base, p0)) / (x(f0_base, p2) - x(f0_base, p0)); k2 = (3 * (y(f0_base, p2) - y(f0_base, p1)) / (x(f0_base, p2) - x(f0_base, p1)) - k1) / 2; } // Normal curve. else { k1 = (y(f0_base, p2) - y(f0_base, p0)) / (x(f0_base, p2) - x(f0_base, p0)); k2 = (y(f0_base, p3) - y(f0_base, p1)) / (x(f0_base, p3) - x(f0_base, p1)); } #if SPLINE_BRUTE_FORCE { interpolate_brute_force(x(f0_base, p1), y(f0_base, p1), x(f0_base, p2), y(f0_base, p2), k1, k2, plotter, res); } #else { interpolate_forward_difference(x(f0_base, p1), y(f0_base, p1), x(f0_base, p2), y(f0_base, p2), k1, k2, plotter, res); } #endif } }
/// <summary> /// Evaluation of cubic polynomial by forward differencing /// </summary> /// <param name="x1"></param> /// <param name="y1"></param> /// <param name="x2"></param> /// <param name="y2"></param> /// <param name="k1"></param> /// <param name="k2"></param> /// <param name="plotter"></param> /// <param name="res"></param> protected void interpolate_forward_difference(double x1, double y1, double x2, double y2, double k1, double k2, PointPlotter plotter, double res) { Coefficients coeff = new Coefficients(); cubic_coefficients(x1, y1, x2, y2, k1, k2, coeff); double y = ((coeff.a * x1 + coeff.b) * x1 + coeff.c) * x1 + coeff.d; double dy = (3 * coeff.a * (x1 + res) + 2 * coeff.b) * x1 * res + ((coeff.a * res + coeff.b) * res + coeff.c) * res; double d2y = (6 * coeff.a * (x1 + res) + 2 * coeff.b) * res * res; double d3y = 6 * coeff.a * res * res * res; // Calculate each point for (double x = x1; x <= x2; x += res) { plotter.plot(x, y); y += dy; dy += d2y; d2y += d3y; } }
/// <summary> /// Evaluation of cubic polynomial by brute force /// </summary> /// <param name="x1"></param> /// <param name="y1"></param> /// <param name="x2"></param> /// <param name="y2"></param> /// <param name="k1"></param> /// <param name="k2"></param> /// <param name="plotter"></param> /// <param name="res"></param> protected void interpolate_brute_force(double x1, double y1, double x2, double y2, double k1, double k2, PointPlotter plotter, double res) { Coefficients coeff = new Coefficients(); cubic_coefficients(x1, y1, x2, y2, k1, k2, coeff); // Calculate each point for (double x = x1; x <= x2; x += res) { double y = ((coeff.a * x + coeff.b) * x + coeff.c) * x + coeff.d; plotter.plot(x, y); } }