SuperTuxKart
interpolation_array.hpp
1 //
2 // SuperTuxKart - a fun racing game with go-kart
3 // Copyright (C) 2012-2015 Joerg Henrichs
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 3
8 // of the License, or (at your option) any later version.
9 //
10 // This program 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
13 // GNU General Public License for more details.
14 //
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 
19 
20 #ifndef HEADER_INTERPOLATION_ARRAY_HPP
21 #define HEADER_INTERPOLATION_ARRAY_HPP
22 
23 #include <assert.h>
24 #include <vector>
25 
32 {
33 private:
35  std::vector<float> m_x;
36 
38  std::vector<float> m_y;
39 
40  /* Pre-computed (x[i+1]-x[i])/(y[i+1]/-y[i]) . */
41  std::vector<float> m_delta;
42 
43 public:
44  InterpolationArray() {};
45 
47  void clear()
48  {
49  m_x.clear();
50  m_y.clear();
51  m_delta.clear();
52  }
53 
58  int push_back(float x, float y)
59  {
60  if(m_x.size()>0 && x < m_x[m_x.size()-1])
61  return 0;
62  m_x.push_back(x);
63  m_y.push_back(y);
64  if(m_y.size()>1)
65  {
66  const unsigned int last=(unsigned int) m_x.size()-1;
67  // Avoid division by zero, just set m_delta to a large
68  // value with the right sign
69  if(m_x[last]==m_x[last-1])
70  m_delta.push_back( (m_y[last]-m_y[last-1])
71  / 0.001f );
72  else
73  m_delta.push_back( (m_y[last]-m_y[last-1])
74  /(m_x[last]-m_x[last-1]) );
75  }
76  return 1;
77  } // push_back
78  // ------------------------------------------------------------------------
80  unsigned int size() const { return (unsigned int) m_x.size(); }
81  // ------------------------------------------------------------------------
83  float getX(unsigned int i) const { return m_x[i]; }
84  // ------------------------------------------------------------------------
86  float getY(unsigned int i) const { return m_y[i]; }
87  // ------------------------------------------------------------------------
89  void setY(unsigned int i, float y)
90  {
91  m_y[i] = y;
92  if(i>0)
93  m_delta[i-1] = (m_y[i]-m_y[i-1])
94  /(m_x[i]-m_x[i-1]);
95  if(i<m_y.size()-1)
96  m_delta[i] = (m_y[i+1]-m_y[i])
97  /(m_x[i+1]-m_x[i]);
98  }
99  // ------------------------------------------------------------------------
101  float get(float x) const
102  {
103  if(m_x.size()==1 || x<m_x[0])
104  return m_y[0];
105 
106  if(x>m_x[m_x.size()-1])
107  return m_y[m_y.size()-1];
108 
109  // Now x must be between two points in m_x
110  // The array size in STK are pretty small (typically 3 or 4),
111  // so not worth the effort to do a binary search
112  for(unsigned int i=1; i<m_x.size(); i++)
113  {
114  if(x >m_x[i]) continue;
115  return m_y[i-1] + m_delta[i-1] * (x - m_x[i-1]);
116  }
117  assert(false); return 0; // keep compiler happy
118  } // get
119 
120  // ------------------------------------------------------------------------
124  float getReverse(float y) const
125  {
126  if(m_y.size()==1) return m_x[0];
127 
128  if(m_y[1]<m_y[0]) // if decreasing values
129  {
130  if(y > m_y[0]) return m_x[0];
131 
132  const unsigned int last = (unsigned int) m_x.size();
133 
134  for(unsigned int i=1; i<last; i++)
135  {
136  if(y < m_y[i]) continue;
137  return m_x[i-1] + (y-m_y[i-1])/ m_delta[i-1];
138  } // for i < last
139  return m_x[last-1];
140  }
141  else // increasing
142  {
143  if(y < m_y[0]) return m_x[0];
144 
145  const unsigned int last = (unsigned int) m_x.size();
146 
147  for(unsigned int i=1; i<last; i++)
148  {
149  if(y > m_y[i]) continue;
150  return m_x[i-1] + (y-m_y[i-1]) / m_delta[i-1];
151  } // for i < last
152  return m_x[last-1];
153  } // increasing
154  } // getReverse
155 }; // InterpolationArray
156 
157 
158 #endif
This class manages a set of (x_i,y_i) points, x_i must be sorted.
Definition: interpolation_array.hpp:32
void setY(unsigned int i, float y)
Sets the Y value for a specified point.
Definition: interpolation_array.hpp:89
float getReverse(float y) const
Returns the X value necessary for a specified Y value.
Definition: interpolation_array.hpp:124
float getX(unsigned int i) const
Returns the X value for a specified point.
Definition: interpolation_array.hpp:83
float get(float x) const
Returns the interpolated Y value for a given x.
Definition: interpolation_array.hpp:101
unsigned int size() const
Returns the number of X/Y points.
Definition: interpolation_array.hpp:80
std::vector< float > m_y
The y values.
Definition: interpolation_array.hpp:38
float getY(unsigned int i) const
Returns the Y value for a specified point.
Definition: interpolation_array.hpp:86
std::vector< float > m_x
The sorted x values.
Definition: interpolation_array.hpp:35
int push_back(float x, float y)
Adds the value pair x/y to the list of all points.
Definition: interpolation_array.hpp:58
void clear()
Removes all saved values from this object.
Definition: interpolation_array.hpp:47