X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fmath%2Finterpolater.cxx;h=cbbb31cfa790582d630b684bb8d98028f185462c;hb=ba83177019da0c941f55b6ef3b709ed7a57d4155;hp=206e99a723e5e5c839782e820dd6060e87eb5657;hpb=75911b6c643d8e5597565bc63c34bdc2009a037a;p=simgear.git diff --git a/simgear/math/interpolater.cxx b/simgear/math/interpolater.cxx index 206e99a7..cbbb31cf 100644 --- a/simgear/math/interpolater.cxx +++ b/simgear/math/interpolater.cxx @@ -4,7 +4,7 @@ // // 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 library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public @@ -16,92 +16,125 @@ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Library General Public License for more details. // -// You should have received a copy of the GNU Library General Public -// License along with this library; if not, write to the -// Free Software Foundation, Inc., 59 Temple Place - Suite 330, -// Boston, MA 02111-1307, USA. +// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // // $Id$ +#ifdef HAVE_CONFIG_H +# include +#endif #include -#include // for exit() +#include -#include STL_STRING - -// depricated - #include #include -#include +#include +#include +#include #include "interpolater.hxx" -SG_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 -SGInterpTable::SGInterpTable( const string& file ) { +SGInterpTable::SGInterpTable( const std::string& file ) +{ SG_LOG( SG_MATH, SG_INFO, "Initializing Interpolator for " << file ); - fg_gzifstream in( file ); + sg_gzifstream in( SGPath::fromUtf8(file) ); if ( !in.is_open() ) { SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << file ); - exit(-1); + return; } - size = 0; in >> skipcomment; while ( in ) { - if ( size < MAX_TABLE_SIZE ) { - in >> table[size][0] >> table[size][1]; - in >> skipws; - size++; - } else { - SG_LOG( SG_MATH, SG_ALERT, - "fgInterpolateInit(): Exceed max table size = " - << MAX_TABLE_SIZE ); - exit(-1); - } + double ind, dep; + in >> ind >> dep; + in >> std::skipws; + _table[ind] = dep; } } -// Given an x value, linearly interpolate the y value from the table -double SGInterpTable::interpolate(double x) { - int i; - double y; - - i = 0; +// Constructor -- loads the interpolation table from the specified +// file +SGInterpTable::SGInterpTable( const SGPath& file ) +{ + SG_LOG( SG_MATH, SG_INFO, "Initializing Interpolator for " << file ); - while ( (x > table[i][0]) && (i < size) ) { - // cout << " i = " << i << " table[i][0] = " << table[i][0] << endl; - // cout << " size = " << size << endl; - i++; + sg_gzifstream in( file ); + if ( !in.is_open() ) { + SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << file ); + return; } - // printf ("i = %d ", i); - - if ( (i == 0) && (x < table[0][0]) ) { - SG_LOG( SG_MATH, SG_DEBUG, - "interpolate(): lookup error, x to small = " << x ); - return table[0][1]; + in >> skipcomment; + while ( in ) { + double ind, dep; + in >> ind >> dep; + in >> std::skipws; + _table[ind] = dep; } +} - // cout << " table[size-1][0] = " << table[size-1][0] << endl; - if ( x > table[size-1][0] ) { - SG_LOG( SG_MATH, SG_DEBUG, - "interpolate(): lookup error, x to big = " << x ); - return table[size-1][1]; - } - // 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); }