X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fmath%2Finterpolater.cxx;h=1bbbadc801d2a427ccd91cb8ac66cb3ef18d7f6e;hb=7a52c2fa71355631a559d74e0860fa6c5efa424e;hp=fb6fdfef482130d8c2cb2d80a370f108ac30ff33;hpb=5173d709e090b953eaf800cbcd1bf897de332a12;p=simgear.git diff --git a/simgear/math/interpolater.cxx b/simgear/math/interpolater.cxx index fb6fdfef..1bbbadc8 100644 --- a/simgear/math/interpolater.cxx +++ b/simgear/math/interpolater.cxx @@ -4,104 +4,123 @@ // // Written by Curtis Olson, started April 1998. // -// Copyright (C) 1998 Curtis L. Olson - curt@me.umn.edu +// Copyright (C) 1998 Curtis L. Olson - http://www.flightgear.org/~curt // -// This program 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 2 of the -// License, or (at your option) any later version. +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. // -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of +// This library 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. +// Library General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software -// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // // $Id$ +#ifdef HAVE_CONFIG_H +# include +#endif #include -#ifdef __MWERKS__ -#include // for exit() -#endif - -#include STL_STRING +#include -#include -#include -#include +#include +#include +#include #include "interpolater.hxx" +#include + +using std::string; + +// Constructor -- starts with an empty table. +SGInterpTable::SGInterpTable() +{ +} + +SGInterpTable::SGInterpTable(const SGPropertyNode* interpolation) +{ + if (!interpolation) + return; + std::vector entries = interpolation->getChildren("entry"); + for (unsigned i = 0; i < entries.size(); ++i) + addEntry(entries[i]->getDoubleValue("ind", 0.0), + entries[i]->getDoubleValue("dep", 0.0)); +} // Constructor -- loads the interpolation table from the specified // file -fgINTERPTABLE::fgINTERPTABLE( const string& file ) { - FG_LOG( FG_MATH, FG_INFO, "Initializing Interpolator for " << file ); - - fg_gzifstream in( file ); - if ( !in ) { - FG_LOG( FG_GENERAL, FG_ALERT, "Cannot open file: " << file ); - exit(-1); +SGInterpTable::SGInterpTable( const string& file ) +{ + SG_LOG( SG_MATH, SG_INFO, "Initializing Interpolator for " << file ); + + sg_gzifstream in( file ); + if ( !in.is_open() ) { + SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << file ); + return; } - size = 0; in >> skipcomment; while ( in ) { - if ( size < MAX_TABLE_SIZE ) { - in >> table[size][0] >> table[size][1]; - size++; - } else { - FG_LOG( FG_MATH, FG_ALERT, - "fgInterpolateInit(): Exceed max table size = " - << MAX_TABLE_SIZE ); - exit(-1); - } + double ind, dep; + in >> ind >> dep; + in >> skipws; + _table[ind] = dep; } } -// Given an x value, linearly interpolate the y value from the table -double fgINTERPTABLE::interpolate(double x) { - int i; - double y; - - i = 0; - - while ( (x > table[i][0]) && (i < size) ) { - i++; - } - - // printf ("i = %d ", i); - - if ( (i == 0) && (x < table[0][0]) ) { - FG_LOG( FG_MATH, FG_ALERT, - "fgInterpolateInit(): lookup error, x to small = " << x ); - return(0.0); - } - - if ( x > table[i][0] ) { - FG_LOG( FG_MATH, FG_ALERT, - "fgInterpolateInit(): lookup error, x to big = " << x ); - return(0.0); - } - - // y = y1 + (y0 - y1)(x - x1) / (x0 - x1) - y = table[i][1] + - ( (table[i-1][1] - table[i][1]) * - (x - table[i][0]) ) / - (table[i-1][0] - table[i][0]); +// Add an entry to the table. +void SGInterpTable::addEntry (double ind, double dep) +{ + _table[ind] = dep; +} - return(y); +// Given an x value, linearly interpolate the y value from the table +double SGInterpTable::interpolate(double x) const +{ + // Empty table?? + if (_table.empty()) + return 0; + + // Find the table bounds for the requested input. + Table::const_iterator upBoundIt = _table.upper_bound(x); + // points to a value outside the map. That is we are out of range. + // use the last entry + if (upBoundIt == _table.end()) + return _table.rbegin()->second; + + // points to the first key must be lower + // use the first entry + if (upBoundIt == _table.begin()) + return upBoundIt->second; + + // we know that we do not stand at the beginning, so it is safe to do so + Table::const_iterator loBoundIt = upBoundIt; + --loBoundIt; + + // Just do linear interpolation. + double loBound = loBoundIt->first; + double upBound = upBoundIt->first; + double loVal = loBoundIt->second; + double upVal = upBoundIt->second; + + // division by zero should not happen since the std::map + // has sorted out duplicate entries before. Also since we have a + // map, we know that we get different first values for different iterators + return loVal + (upVal - loVal)*(x - loBound)/(upBound - loBound); } // Destructor -fgINTERPTABLE::~fgINTERPTABLE( void ) { +SGInterpTable::~SGInterpTable() { }