BicubicSplineInterpolatingFunction implements BivariateFunction { public double value(double x, double y) throws OutOfRangeException { final int i = searchIndex(x, xval); final int j = searchIndex(y, yval); final double xN = (x - xval[i]) / (xval[i + 1] - xval[i]); final double yN = (y - yval[j]) / (yval[j + 1] - yval[j]); return splines[i][j].value(xN, yN); } BicubicSplineInterpolatingFunction(double[] x,
                                              double[] y,
                                              double[][] f,
                                              double[][] dFdX,
                                              double[][] dFdY,
                                              double[][] d2FdXdY);  BicubicSplineInterpolatingFunction(double[] x,
                                              double[] y,
                                              double[][] f,
                                              double[][] dFdX,
                                              double[][] dFdY,
                                              double[][] d2FdXdY,
                                              boolean initializeDerivatives); double value(double x, double y); boolean isValidPoint(double x, double y); double partialDerivativeX(double x, double y); double partialDerivativeY(double x, double y); double partialDerivativeXX(double x, double y); double partialDerivativeYY(double x, double y); double partialDerivativeXY(double x, double y);  }
@Ignore@Test public void testPlane() { double[] xval = new double[] {3, 4, 5, 6.5}; double[] yval = new double[] {-4, -3, -1, 2, 2.5}; BivariateFunction f = new BivariateFunction() { public double value(double x, double y) { return 2 * x - 3 * y + 5; } }; double[][] zval = new double[xval.length][yval.length]; for (int i = 0; i < xval.length; i++) { for (int j = 0; j < yval.length; j++) { zval[i][j] = f.value(xval[i], yval[j]); } } double[][] dZdX = new double[xval.length][yval.length]; for (int i = 0; i < xval.length; i++) { for (int j = 0; j < yval.length; j++) { dZdX[i][j] = 2; } } double[][] dZdY = new double[xval.length][yval.length]; for (int i = 0; i < xval.length; i++) { for (int j = 0; j < yval.length; j++) { dZdY[i][j] = -3; } } double[][] dZdXdY = new double[xval.length][yval.length]; for (int i = 0; i < xval.length; i++) { for (int j = 0; j < yval.length; j++) { dZdXdY[i][j] = 0; } } BivariateFunction bcf = new BicubicSplineInterpolatingFunction(xval, yval, zval, dZdX, dZdY, dZdXdY); double x, y; double expected, result; x = 4; y = -3; expected = f.value(x, y); result = bcf.value(x, y); Assert.assertEquals("On sample point", expected, result, 1e-15); x = 4.5; y = -1.5; expected = f.value(x, y); result = bcf.value(x, y); Assert.assertEquals("Half-way between sample points (middle of the patch)", expected, result, 0.3); x = 3.5; y = -3.5; expected = f.value(x, y); result = bcf.value(x, y); Assert.assertEquals("Half-way between sample points (border of the patch)", expected, result, 0.3); }
@Ignore@Test public void testParaboloid() { double[] xval = new double[] {3, 4, 5, 6.5}; double[] yval = new double[] {-4, -3, -1, 2, 2.5}; BivariateFunction f = new BivariateFunction() { public double value(double x, double y) { return 2 * x * x - 3 * y * y + 4 * x * y - 5; } }; double[][] zval = new double[xval.length][yval.length]; for (int i = 0; i < xval.length; i++) { for (int j = 0; j < yval.length; j++) { zval[i][j] = f.value(xval[i], yval[j]); } } double[][] dZdX = new double[xval.length][yval.length]; BivariateFunction dfdX = new BivariateFunction() { public double value(double x, double y) { return 4 * (x + y); } }; for (int i = 0; i < xval.length; i++) { for (int j = 0; j < yval.length; j++) { dZdX[i][j] = dfdX.value(xval[i], yval[j]); } } double[][] dZdY = new double[xval.length][yval.length]; BivariateFunction dfdY = new BivariateFunction() { public double value(double x, double y) { return 4 * x - 6 * y; } }; for (int i = 0; i < xval.length; i++) { for (int j = 0; j < yval.length; j++) { dZdY[i][j] = dfdY.value(xval[i], yval[j]); } } double[][] dZdXdY = new double[xval.length][yval.length]; for (int i = 0; i < xval.length; i++) { for (int j = 0; j < yval.length; j++) { dZdXdY[i][j] = 4; } } BivariateFunction bcf = new BicubicSplineInterpolatingFunction(xval, yval, zval, dZdX, dZdY, dZdXdY); double x, y; double expected, result; x = 4; y = -3; expected = f.value(x, y); result = bcf.value(x, y); Assert.assertEquals("On sample point", expected, result, 1e-15); x = 4.5; y = -1.5; expected = f.value(x, y); result = bcf.value(x, y); Assert.assertEquals("Half-way between sample points (middle of the patch)", expected, result, 2); x = 3.5; y = -3.5; expected = f.value(x, y); result = bcf.value(x, y); Assert.assertEquals("Half-way between sample points (border of the patch)", expected, result, 2); }
@Test public void testInterpolation1() { final int sz = 21; double[] xval = new double[sz]; double[] yval = new double[sz]; final double delta = 1d / (sz - 1); for (int i = 0; i < sz; i++) { xval[i] = -1 + 15 * i * delta; yval[i] = -20 + 30 * i * delta; } BivariateFunction f = new BivariateFunction() { public double value(double x, double y) { return 2 * x - 3 * y + 5; } }; double[][] zval = new double[xval.length][yval.length]; for (int i = 0; i < xval.length; i++) { for (int j = 0; j < yval.length; j++) { zval[i][j] = f.value(xval[i], yval[j]); } } double[][] dZdX = new double[xval.length][yval.length]; for (int i = 0; i < xval.length; i++) { for (int j = 0; j < yval.length; j++) { dZdX[i][j] = 2; } } double[][] dZdY = new double[xval.length][yval.length]; for (int i = 0; i < xval.length; i++) { for (int j = 0; j < yval.length; j++) { dZdY[i][j] = -3; } } double[][] dZdXdY = new double[xval.length][yval.length]; for (int i = 0; i < xval.length; i++) { for (int j = 0; j < yval.length; j++) { dZdXdY[i][j] = 0; } } final BivariateFunction bcf = new BicubicSplineInterpolatingFunction(xval, yval, zval, dZdX, dZdY, dZdXdY); double x, y; final RandomGenerator rng = new Well19937c(1234567L); final UniformRealDistribution distX = new UniformRealDistribution(rng, xval[0], xval[xval.length - 1]); final UniformRealDistribution distY = new UniformRealDistribution(rng, yval[0], yval[yval.length - 1]); final int numSamples = 50; final double tol = 6; for (int i = 0; i < numSamples; i++) { x = distX.sample(); for (int j = 0; j < numSamples; j++) { y = distY.sample(); Assert.assertEquals(f.value(x, y), bcf.value(x, y), tol); } } }
@Test public void testInterpolation2() { final int sz = 21; double[] xval = new double[sz]; double[] yval = new double[sz]; final double delta = 1d / (sz - 1); for (int i = 0; i < sz; i++) { xval[i] = -1 + 15 * i * delta; yval[i] = -20 + 30 * i * delta; } BivariateFunction f = new BivariateFunction() { public double value(double x, double y) { return 2 * x * x - 3 * y * y + 4 * x * y - 5; } }; double[][] zval = new double[xval.length][yval.length]; for (int i = 0; i < xval.length; i++) { for (int j = 0; j < yval.length; j++) { zval[i][j] = f.value(xval[i], yval[j]); } } double[][] dZdX = new double[xval.length][yval.length]; BivariateFunction dfdX = new BivariateFunction() { public double value(double x, double y) { return 4 * (x + y); } }; for (int i = 0; i < xval.length; i++) { for (int j = 0; j < yval.length; j++) { dZdX[i][j] = dfdX.value(xval[i], yval[j]); } } double[][] dZdY = new double[xval.length][yval.length]; BivariateFunction dfdY = new BivariateFunction() { public double value(double x, double y) { return 4 * x - 6 * y; } }; for (int i = 0; i < xval.length; i++) { for (int j = 0; j < yval.length; j++) { dZdY[i][j] = dfdY.value(xval[i], yval[j]); } } double[][] dZdXdY = new double[xval.length][yval.length]; for (int i = 0; i < xval.length; i++) { for (int j = 0; j < yval.length; j++) { dZdXdY[i][j] = 4; } } BivariateFunction bcf = new BicubicSplineInterpolatingFunction(xval, yval, zval, dZdX, dZdY, dZdXdY); double x, y; final RandomGenerator rng = new Well19937c(1234567L); final UniformRealDistribution distX = new UniformRealDistribution(rng, xval[0], xval[xval.length - 1]); final UniformRealDistribution distY = new UniformRealDistribution(rng, yval[0], yval[yval.length - 1]); final double tol = 224; for (int i = 0; i < sz; i++) { x = distX.sample(); for (int j = 0; j < sz; j++) { y = distY.sample(); Assert.assertEquals(f.value(x, y), bcf.value(x, y), tol); } } }