1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.commons.math.analysis.interpolation; 18 19 import org.apache.commons.math.exception.DimensionMismatchException; 20 import org.apache.commons.math.exception.NoDataException; 21 import org.apache.commons.math.MathException; 22 import org.apache.commons.math.util.MathUtils; 23 import org.apache.commons.math.optimization.general.GaussNewtonOptimizer; 24 import org.apache.commons.math.optimization.fitting.PolynomialFitter; 25 import org.apache.commons.math.analysis.polynomials.PolynomialFunction; 26 27 /** 28 * Generates a bicubic interpolation function. 29 * Prior to generating the interpolating function, the input is smoothed using 30 * polynomial fitting. 31 * 32 * @version $Revision: 1003892 $ $Date: 2010-10-02 23:28:56 +0200 (sam. 02 oct. 2010) $ 33 * @since 2.2 34 */ 35 public class SmoothingPolynomialBicubicSplineInterpolator 36 extends BicubicSplineInterpolator { 37 38 /** Fitter for x. */ 39 private final PolynomialFitter xFitter; 40 41 /** Fitter for y. */ 42 private final PolynomialFitter yFitter; 43 44 /** 45 * Default constructor. The degree of the fitting polynomials is set to 3. 46 */ 47 public SmoothingPolynomialBicubicSplineInterpolator() { 48 this(3); 49 } 50 51 /** 52 * @param degree Degree of the polynomial fitting functions. 53 */ 54 public SmoothingPolynomialBicubicSplineInterpolator(int degree) { 55 this(degree, degree); 56 } 57 58 /** 59 * @param xDegree Degree of the polynomial fitting functions along the 60 * x-dimension. 61 * @param yDegree Degree of the polynomial fitting functions along the 62 * y-dimension. 63 */ 64 public SmoothingPolynomialBicubicSplineInterpolator(int xDegree, 65 int yDegree) { 66 xFitter = new PolynomialFitter(xDegree, new GaussNewtonOptimizer(false)); 67 yFitter = new PolynomialFitter(yDegree, new GaussNewtonOptimizer(false)); 68 } 69 70 /** 71 * {@inheritDoc} 72 */ 73 @Override 74 public BicubicSplineInterpolatingFunction interpolate(final double[] xval, 75 final double[] yval, 76 final double[][] fval) 77 throws MathException { 78 if (xval.length == 0 || yval.length == 0 || fval.length == 0) { 79 throw new NoDataException(); 80 } 81 if (xval.length != fval.length) { 82 throw new DimensionMismatchException(xval.length, fval.length); 83 } 84 85 final int xLen = xval.length; 86 final int yLen = yval.length; 87 88 for (int i = 0; i < xLen; i++) { 89 if (fval[i].length != yLen) { 90 throw new DimensionMismatchException(fval[i].length, yLen); 91 } 92 } 93 94 MathUtils.checkOrder(xval); 95 MathUtils.checkOrder(yval); 96 97 // For each line y[j] (0 <= j < yLen), construct a polynomial, with 98 // respect to variable x, fitting array fval[][j] 99 final PolynomialFunction[] yPolyX = new PolynomialFunction[yLen]; 100 for (int j = 0; j < yLen; j++) { 101 xFitter.clearObservations(); 102 for (int i = 0; i < xLen; i++) { 103 xFitter.addObservedPoint(1, xval[i], fval[i][j]); 104 } 105 106 yPolyX[j] = xFitter.fit(); 107 } 108 109 // For every knot (xval[i], yval[j]) of the grid, calculate corrected 110 // values fval_1 111 final double[][] fval_1 = new double[xLen][yLen]; 112 for (int j = 0; j < yLen; j++) { 113 final PolynomialFunction f = yPolyX[j]; 114 for (int i = 0; i < xLen; i++) { 115 fval_1[i][j] = f.value(xval[i]); 116 } 117 } 118 119 // For each line x[i] (0 <= i < xLen), construct a polynomial, with 120 // respect to variable y, fitting array fval_1[i][] 121 final PolynomialFunction[] xPolyY = new PolynomialFunction[xLen]; 122 for (int i = 0; i < xLen; i++) { 123 yFitter.clearObservations(); 124 for (int j = 0; j < yLen; j++) { 125 yFitter.addObservedPoint(1, yval[j], fval_1[i][j]); 126 } 127 128 xPolyY[i] = yFitter.fit(); 129 } 130 131 // For every knot (xval[i], yval[j]) of the grid, calculate corrected 132 // values fval_2 133 final double[][] fval_2 = new double[xLen][yLen]; 134 for (int i = 0; i < xLen; i++) { 135 final PolynomialFunction f = xPolyY[i]; 136 for (int j = 0; j < yLen; j++) { 137 fval_2[i][j] = f.value(yval[j]); 138 } 139 } 140 141 return super.interpolate(xval, yval, fval_2); 142 } 143 } 144