SmoothingPolynomialBicubicSplineInterpolator extends BicubicSplineInterpolator { @Override public BicubicSplineInterpolatingFunction interpolate(final double[] xval, final double[] yval, final double[][] fval) throws NoDataException, NullArgumentException, DimensionMismatchException, NonMonotonicSequenceException { if (xval.length == 0 || yval.length == 0 || fval.length == 0) { throw new NoDataException(); } if (xval.length != fval.length) { throw new DimensionMismatchException(xval.length, fval.length); } final int xLen = xval.length; final int yLen = yval.length; for (int i = 0; i < xLen; i++) { if (fval[i].length != yLen) { throw new DimensionMismatchException(fval[i].length, yLen); } } MathArrays.checkOrder(xval); MathArrays.checkOrder(yval); final PolynomialFunction[] yPolyX = new PolynomialFunction[yLen]; for (int j = 0; j < yLen; j++) { xFitter.clearObservations(); for (int i = 0; i < xLen; i++) { xFitter.addObservedPoint(1, xval[i], fval[i][j]); } yPolyX[j] = new PolynomialFunction(xFitter.fit(new double[xDegree + 1])); } final double[][] fval_1 = new double[xLen][yLen]; for (int j = 0; j < yLen; j++) { final PolynomialFunction f = yPolyX[j]; for (int i = 0; i < xLen; i++) { fval_1[i][j] = f.value(xval[i]); } } final PolynomialFunction[] xPolyY = new PolynomialFunction[xLen]; for (int i = 0; i < xLen; i++) { yFitter.clearObservations(); for (int j = 0; j < yLen; j++) { yFitter.addObservedPoint(1, yval[j], fval_1[i][j]); } xPolyY[i] = new PolynomialFunction(yFitter.fit(new double[yDegree + 1])); } final double[][] fval_2 = new double[xLen][yLen]; for (int i = 0; i < xLen; i++) { final PolynomialFunction f = xPolyY[i]; for (int j = 0; j < yLen; j++) { fval_2[i][j] = f.value(yval[j]); } } return super.interpolate(xval, yval, fval_2); } SmoothingPolynomialBicubicSplineInterpolator();  SmoothingPolynomialBicubicSplineInterpolator(int degree);  SmoothingPolynomialBicubicSplineInterpolator(int xDegree, int yDegree); @Override BicubicSplineInterpolatingFunction interpolate(final double[] xval,
                                                          final double[] yval,
                                                          final double[][] fval);  }
@Test public void testPreconditions() { double[] xval = new double[] {3, 4, 5, 6.5, 7.5}; double[] yval = new double[] {-4, -3, -1, 2.5, 3}; double[][] zval = new double[xval.length][yval.length]; BivariateGridInterpolator interpolator = new SmoothingPolynomialBicubicSplineInterpolator(0); @SuppressWarnings("unused") BivariateFunction p = interpolator.interpolate(xval, yval, zval); double[] wxval = new double[] {3, 2, 5, 6.5}; try { p = interpolator.interpolate(wxval, yval, zval); Assert.fail("an exception should have been thrown"); } catch (MathIllegalArgumentException e) { } double[] wyval = new double[] {-4, -3, -1, -1}; try { p = interpolator.interpolate(xval, wyval, zval); Assert.fail("an exception should have been thrown"); } catch (MathIllegalArgumentException e) { } double[][] wzval = new double[xval.length][yval.length + 1]; try { p = interpolator.interpolate(xval, yval, wzval); Assert.fail("an exception should have been thrown"); } catch (DimensionMismatchException e) { } wzval = new double[xval.length - 1][yval.length]; try { p = interpolator.interpolate(xval, yval, wzval); Assert.fail("an exception should have been thrown"); } catch (DimensionMismatchException e) { } wzval = new double[xval.length][yval.length - 1]; try { p = interpolator.interpolate(xval, yval, wzval); Assert.fail("an exception should have been thrown"); } catch (DimensionMismatchException e) { } }
@Test public void testPlane() { BivariateFunction f = new BivariateFunction() { public double value(double x, double y) { return 2 * x - 3 * y + 5 + ((int) (FastMath.abs(5 * x + 3 * y)) % 2 == 0 ? 1 : -1); } }; BivariateGridInterpolator interpolator = new SmoothingPolynomialBicubicSplineInterpolator(1); double[] xval = new double[] {3, 4, 5, 6.5, 7.5}; double[] yval = new double[] {-4, -3, -1, 2, 2.5, 3.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]); } } BivariateFunction p = interpolator.interpolate(xval, yval, zval); double x, y; double expected, result; x = 4; y = -3; expected = f.value(x, y); result = p.value(x, y); Assert.assertEquals("On sample point", expected, result, 2); x = 4.5; y = -1.5; expected = f.value(x, y); result = p.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 = p.value(x, y); Assert.assertEquals("half-way between sample points (border of the patch)", expected, result, 2); }
@Test public void testParaboloid() { BivariateFunction f = new BivariateFunction() { public double value(double x, double y) { return 2 * x * x - 3 * y * y + 4 * x * y - 5 + ((int) (FastMath.abs(5 * x + 3 * y)) % 2 == 0 ? 1 : -1); } }; BivariateGridInterpolator interpolator = new SmoothingPolynomialBicubicSplineInterpolator(4); double[] xval = new double[] {3, 4, 5, 6.5, 7.5, 8}; double[] yval = new double[] {-4, -3, -2, -1, 0.5, 2.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]); } } BivariateFunction p = interpolator.interpolate(xval, yval, zval); double x, y; double expected, result; x = 5; y = 0.5; expected = f.value(x, y); result = p.value(x, y); Assert.assertEquals("On sample point", expected, result, 2); x = 4.5; y = -1.5; expected = f.value(x, y); result = p.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 = p.value(x, y); Assert.assertEquals("half-way between sample points (border of the patch)", expected, result, 2); }