X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fmath%2Finterpolater.cxx;h=1bbbadc801d2a427ccd91cb8ac66cb3ef18d7f6e;hb=11479cd8c386d8bf7e1fee7bed60ab4abefc5fad;hp=ccb71d6be5b783e5aea6e06750040e5e106ba306;hpb=e4bbc5c50b079ff2c6f00c6e2e650502f2ae95f8;p=simgear.git diff --git a/simgear/math/interpolater.cxx b/simgear/math/interpolater.cxx index ccb71d6b..1bbbadc8 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,46 +16,55 @@ // 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 "interpolater.hxx" -SG_USING_STD(string); +#include + +using std::string; // Constructor -- starts with an empty table. SGInterpTable::SGInterpTable() - : size(0) { } +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 ) - : size(0) { 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 ); - exit(-1); + return; } in >> skipcomment; @@ -63,8 +72,7 @@ SGInterpTable::SGInterpTable( const string& file ) double ind, dep; in >> ind >> dep; in >> skipws; - table.push_back(Entry(ind, dep)); - size++; + _table[ind] = dep; } } @@ -72,51 +80,42 @@ SGInterpTable::SGInterpTable( const string& file ) // Add an entry to the table. void SGInterpTable::addEntry (double ind, double dep) { - table.push_back(Entry(ind,dep)); - size++; + _table[ind] = dep; } - // Given an x value, linearly interpolate the y value from the table double SGInterpTable::interpolate(double x) const { - int i; - double y; - - if (size == 0.0) { - return 0.0; - } - - i = 0; - - while ( (i < size) && (x > table[i].ind) ) { - // cout << " i = " << i << " table[i].ind = " << table[i].ind << endl; - // cout << " size = " << size << endl; - i++; - } - - // printf ("i = %d ", i); - - if ( i <= 0 ) { - SG_LOG( SG_MATH, SG_DEBUG, - "interpolate(): lookup error, x to small = " << x ); - return table[0].dep; - } - - // cout << " table[size-1].ind = " << table[size-1].ind << endl; - if ( i >= size ) { - SG_LOG( SG_MATH, SG_DEBUG, - "interpolate(): lookup error, x to big = " << x ); - return table[size-1].dep; - } - - // y = y1 + (y0 - y1)(x - x1) / (x0 - x1) - y = table[i].dep + - ( (table[i-1].dep - table[i].dep) * - (x - table[i].ind) ) / - (table[i-1].ind - table[i].ind); - - return(y); + // 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); }