1 // Written by Andrew J. Ross, started December 2003
3 // Copyright (C) 2003 Andrew J. Ross - andy@plausible.org
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Library General Public
7 // License as published by the Free Software Foundation; either
8 // version 2 of the License, or (at your option) any later version.
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Library General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 #include "interpolator.hxx"
21 #include <simgear/math/SGMath.hxx>
23 void SGInterpolator::addNew(SGPropertyNode* prop, int nPoints)
25 // Set the property type to a double, if it isn't already, and
26 // make sure we aren't already managing this node.
27 prop->setDoubleValue(prop->getDoubleValue());
30 Interp* iterp = new Interp();
32 iterp->nPoints = nPoints;
33 iterp->curve = new double[2*nPoints];
35 // Dirty trick: leave the new value sitting in _list to avoid
36 // having to return a pointer to a private type.
41 void SGInterpolator::interpolate(SGPropertyNode* prop, int nPoints,
42 double* values, double* deltas)
44 addNew(prop, nPoints);
45 for(int i=0; i<nPoints; i++) {
46 _list->dt(i) = deltas[i];
47 _list->val(i) = values[i];
51 void SGInterpolator::interpolate(SGPropertyNode* prop, double val, double dt)
59 // Delete all the list elements where "expr" is true.
61 // Silly preprocessor hack to avoid writing the linked list code in
62 // two places. You would think that an STL set would be the way to
63 // go, but I had terrible trouble getting it to work with the
64 // dynamically allocated "curve" member. Frankly, this is easier to
65 // write, and the code is smaller to boot...
67 #define DELETE_WHERE(EXPR)\
68 Interp *p = _list, **last = &_list; \
73 p = (*last) ? (*last)->next : 0; \
78 void SGInterpolator::cancel(SGPropertyNode* prop)
80 DELETE_WHERE(p->target == prop)
83 void SGInterpolator::update(double dt)
85 DELETE_WHERE(interp(p, dt))
88 // This is the where the only "real" work happens. Walk through the
89 // data points until we find one with some time left, slurp it up and
90 // repeat until we run out of dt.
91 bool SGInterpolator::interp(Interp* rec, double dt)
93 double val = rec->target->getDoubleValue();
95 for(i=0; i < rec->nPoints; i++) {
96 if(rec->dt(i) > 0 && dt < rec->dt(i)) {
97 val += (dt / rec->dt(i)) * (rec->val(i) - val);
104 rec->target->setDoubleValue(val);
106 // Return true if this one is done
107 return i == rec->nPoints;