/* * Copyright 2010-2015 Institut Pasteur. * * This file is part of Icy. * * Icy is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Icy is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Icy. If not, see <http://www.gnu.org/licenses/>. */ package icy.math; import java.awt.Point; import java.util.ArrayList; import java.util.List; /** * @author stephane */ public class Interpolator { private static double[][] pointsToXY(List<Point> points) { final int len = points.size(); final double[][] xy = new double[2][len]; final double[] x = xy[0]; final double[] y = xy[1]; for (int i = 0; i < len; i++) { final Point p = points.get(i); x[i] = p.x; y[i] = p.y; } return xy; } private static double[] prepareYInterpolation(double[] x, double[] y, double xinc) { if ((x.length == 0) || (y.length == 0)) throw new IllegalArgumentException("x[] and y[] should not be empty."); if (x.length != y.length) throw new IllegalArgumentException("x[] and y[] should have the same length."); if (xinc == 0) throw new IllegalArgumentException("step must be > 0"); return new double[(int) ((x[x.length - 1] - x[0]) / xinc) + 1]; } /** * Return Y linear interpolated coordinates from specified points and given X increment */ public static double[] doYLinearInterpolation(List<Point> points, double xinc) { final double[][] xy = pointsToXY(points); return doYLinearInterpolation(xy[0], xy[1], xinc); } /** * Return Y linear interpolated coordinates from specified points and given X increment */ public static double[] doYLinearInterpolation(double[] x, double[] y, double xinc) { final double[] result = prepareYInterpolation(x, y, xinc); final int len = result.length; if (len == 1) result[0] = x[0]; else { final int xlen = x.length - 1; int index = 0; int offset = 0; double xvalue = x[0]; double yvalue = y[0]; double yinc = 0; while (offset < len) { while ((index < xlen) && (xvalue >= x[index])) { index++; final double dx = x[index] - xvalue; if (dx != 0) yinc = (y[index] - yvalue) / dx; else yinc = 0; } result[offset++] = yvalue; yvalue += yinc; xvalue += xinc; } } return result; } /** * Return Y spline interpolated coordinates from specified points and given X increment */ public static double[] doYSplineInterpolation(ArrayList<Point> points, double xstep) { final double[][] xy = pointsToXY(points); return doYSplineInterpolation(xy[0], xy[1], xstep); } /** * Return Y spline interpolated coordinates from specified points and given X increment.<br> * Not yet implemented ! */ public static double[] doYSplineInterpolation(double[] x, double[] y, double xstep) { final double[] result = prepareYInterpolation(x, y, xstep); final int len = result.length; if (len > 1) { } return result; } /** * Do linear interpolation from start to end with specified increment step */ public static double[] doLinearInterpolation(double start, double end, double step) { int size; if (step == 0) size = 1; else size = (int) ((end - start) / step) + 1; // size should be at least 1 if (size < 1) size = 1; final double[] result = new double[size]; double value = start; for (int i = 0; i < size; i++) { result[i] = value; value += step; } return result; } /** * Do linear interpolation from start to end with specified size (step number) */ public static double[] doLinearInterpolation(double start, double end, int size) { if (size < 1) return null; // special case if (size == 1) { final double[] result = new double[size]; result[0] = end; return result; } return doLinearInterpolation(start, end, (end - start) / (size - 1)); } /** * Do logarithmic interpolation from start to end with specified size (step number) */ public static double[] doLogInterpolation(double start, double end, int size) { // get linear interpolation final double[] result = doLinearInterpolation(start, end, size); // define input and output scaler final Scaler scalerIn = new Scaler(start, end, 2, 20, true, true); final Scaler scalerOut = new Scaler(Math.log(2), Math.log(20), start, end, true, true); final int len = result.length; // log scaling for (int i = 0; i < len; i++) result[i] = scalerOut.scale(Math.log(scalerIn.scale(result[i]))); return result; } /** * Do exponential interpolation from start to end with specified size (step number) */ public static double[] doExpInterpolation(double start, double end, int size) { // get linear interpolation final double[] result = doLinearInterpolation(start, end, size); // define input and output scaler final Scaler scalerIn = new Scaler(start, end, 0, 2, false, true); final Scaler scalerOut = new Scaler(Math.exp(0), Math.exp(2), start, end, false, true); final int len = result.length; // exp scaling for (int i = 0; i < len; i++) result[i] = scalerOut.scale(Math.exp(scalerIn.scale(result[i]))); return result; } }