| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.commons.math.analysis.interpolation; |
| |
| import org.apache.commons.math.exception.DimensionMismatchException; |
| import org.apache.commons.math.exception.NoDataException; |
| import org.apache.commons.math.MathException; |
| import org.apache.commons.math.util.MathUtils; |
| import org.apache.commons.math.optimization.general.GaussNewtonOptimizer; |
| import org.apache.commons.math.optimization.fitting.PolynomialFitter; |
| import org.apache.commons.math.analysis.polynomials.PolynomialFunction; |
| |
| /** |
| * Generates a bicubic interpolation function. |
| * Prior to generating the interpolating function, the input is smoothed using |
| * polynomial fitting. |
| * |
| * @version $Revision: 1003892 $ $Date: 2010-10-02 23:28:56 +0200 (sam. 02 oct. 2010) $ |
| * @since 2.2 |
| */ |
| public class SmoothingPolynomialBicubicSplineInterpolator |
| extends BicubicSplineInterpolator { |
| |
| /** Fitter for x. */ |
| private final PolynomialFitter xFitter; |
| |
| /** Fitter for y. */ |
| private final PolynomialFitter yFitter; |
| |
| /** |
| * Default constructor. The degree of the fitting polynomials is set to 3. |
| */ |
| public SmoothingPolynomialBicubicSplineInterpolator() { |
| this(3); |
| } |
| |
| /** |
| * @param degree Degree of the polynomial fitting functions. |
| */ |
| public SmoothingPolynomialBicubicSplineInterpolator(int degree) { |
| this(degree, degree); |
| } |
| |
| /** |
| * @param xDegree Degree of the polynomial fitting functions along the |
| * x-dimension. |
| * @param yDegree Degree of the polynomial fitting functions along the |
| * y-dimension. |
| */ |
| public SmoothingPolynomialBicubicSplineInterpolator(int xDegree, |
| int yDegree) { |
| xFitter = new PolynomialFitter(xDegree, new GaussNewtonOptimizer(false)); |
| yFitter = new PolynomialFitter(yDegree, new GaussNewtonOptimizer(false)); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public BicubicSplineInterpolatingFunction interpolate(final double[] xval, |
| final double[] yval, |
| final double[][] fval) |
| throws MathException { |
| 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); |
| } |
| } |
| |
| MathUtils.checkOrder(xval); |
| MathUtils.checkOrder(yval); |
| |
| // For each line y[j] (0 <= j < yLen), construct a polynomial, with |
| // respect to variable x, fitting array fval[][j] |
| 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] = xFitter.fit(); |
| } |
| |
| // For every knot (xval[i], yval[j]) of the grid, calculate corrected |
| // values fval_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]); |
| } |
| } |
| |
| // For each line x[i] (0 <= i < xLen), construct a polynomial, with |
| // respect to variable y, fitting array fval_1[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] = yFitter.fit(); |
| } |
| |
| // For every knot (xval[i], yval[j]) of the grid, calculate corrected |
| // values fval_2 |
| 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); |
| } |
| } |