/* * Copyright (C) 2010, 2011, 2012 by Arne Kesting, Martin Treiber, Ralph Germ, Martin Budden * <movsim.org@gmail.com> * ----------------------------------------------------------------------------------------- * * This file is part of * * MovSim - the multi-model open-source vehicular-traffic simulator. * * MovSim 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. * * MovSim 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 MovSim. If not, see <http://www.gnu.org/licenses/> * or <http://www.movsim.org>. * * ----------------------------------------------------------------------------------------- */ package org.movsim.utilities; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * The Class Tables. Various static table-related methods like interpolation, extrapolation */ public class Tables { /** The Constant logger. */ final static Logger logger = LoggerFactory.getLogger(Tables.class); private static final double TINY_VALUE = 1.e-10; private Tables() { } public static double intp(double[] tab, double x, double xmin, double xmax) { return intp(tab, tab.length, x, xmin, xmax); } public static double intp(double[] tab, int n, double x, double xmin, double xmax) { double intp_value = tab[0]; final double ir = n * (x - xmin) / (xmax - xmin); final int i = (int) ir; final double rest = ir - i; if ((i >= 0) && (i < n - 1)) { intp_value = (1 - rest) * tab[i] + rest * tab[i + 1]; } else if (i == n - 1) { intp_value = tab[n - 1]; } else if (i == n) { intp_value = xmax; } else { logger.error("intp: index i = " + i + " (ir=" + ir + ") out of range\n"); System.exit(-1); } return intp_value; } public static double intpextp(double[] x_vals, double[] y_vals, double x) { final int nx = x_vals.length; final int ny = y_vals.length; final int n = Math.min(nx, ny); if (nx != ny) { logger.debug("Warning: arrays of not equal length = {}, {} ", nx, ny); } if (nx == 0 || ny == 0) { // logger.debug("cannot interpolate from arrays with zero length(s) = {}, {}. return 0 ", // nx, ny); return 0; } int i = 0; double intp_value = 0; while ((x_vals[i] <= x) && (i < n - 1)) { i++; } if (i == 0) { // extrapolation to "left" side intp_value = y_vals[0]; } else if ((i == n - 1) && (x > x_vals[i])) { // extrapol. to "right" side intp_value = y_vals[n - 1]; } else if (Math.abs(x_vals[i] - x_vals[i - 1]) < TINY_VALUE) { // treatment // of jumps intp_value = y_vals[i]; } else { // linear interpolation intp_value = y_vals[i - 1] + (y_vals[i] - y_vals[i - 1]) * (x - x_vals[i - 1]) / (x_vals[i] - x_vals[i - 1]); } // logger.debug(" return = {}", intp_value); return (intp_value); } // Version using only the index range imin ... imax and extrapolating // constant values otherwise; reverse=true means that the array x // has x values in decreasing order. NOT TIME OPTIMIZED public static double intpextp(double[] x, double[] y, double pos, boolean reverse) { return intpextp(x, y, pos, 0, x.length - 1, reverse); } public static double intpextp(double[] x, double[] y, double pos, int imin, int imax, boolean reverse) { final double tinyValue = 0.000001; double intp_value; int i = imin; if (reverse) { while ((x[i] >= pos) && (i < imax)) { i++; } } else { while ((x[i] <= pos) && (i < imax)) { i++; } } if (i == imin) { intp_value = y[imin]; // left extrapolation } else if (i == imax) { intp_value = y[imax]; // right extrapolation } else if (Math.abs(x[i] - x[i - 1]) < tinyValue) { intp_value = y[i]; // same x values } else { intp_value = y[i - 1] + (y[i] - y[i - 1]) * (pos - x[i - 1]) / (x[i] - x[i - 1]); // interpolation } return (intp_value); } // TODO check implementation !!! // extrapolate left-hand side values for use in speedlimit public static double stepExtrapolation(double[] x_vals, double[] y_vals, double x) { final int nx = x_vals.length; final int ny = y_vals.length; final int n = Math.min(nx, ny); if (nx != ny) { logger.debug("Warning: arrays of not equal length = {}, {} ", nx, ny); } if (nx == 0 || ny == 0) { logger.debug("cannot interpolate from arrays with zero length(s) = {}, {} ", nx, ny); return 0; } int i = 0; double intp_value; while ((x_vals[i] <= x) && (i < n - 1)) { i++; } if (i == 0) { // extrapolation to "left" side intp_value = y_vals[0]; } else if ((i == n - 1) && (x > x_vals[i])) { // extrapol. to "right" side intp_value = y_vals[n - 1]; } else { // simple constant extrapolation from "left" side intp_value = y_vals[i - 1]; } // else { // linear interpolation // intp_value = y_vals[i - 1] + (y_vals[i] - y_vals[i - 1]) * (x - // x_vals[i - 1]) // / (x_vals[i] - x_vals[i - 1]); // } return (intp_value); } }