Update copyright date; remove old CVS keyword
[ctsim.git] / include / interpolator.h
1 /*****************************************************************************
2 **  This is part of the CTSim program
3 **  Copyright (c) 1983-2009 Kevin Rosenberg
4 **
5 **  This program is free software; you can redistribute it and/or modify
6 **  it under the terms of the GNU General Public License (version 2) as
7 **  published by the Free Software Foundation.
8 **
9 **  This program is distributed in the hope that it will be useful,
10 **  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 **  GNU General Public License for more details.
13 **
14 **  You should have received a copy of the GNU General Public License
15 **  along with this program; if not, write to the Free Software
16 **  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17 ******************************************************************************/
18
19
20 class CubicSplineInterpolator {
21 private:
22   double *m_pdY2;  // second differential of y data
23
24   const double* const m_pdY;
25   const int m_n;
26
27 public:
28   CubicSplineInterpolator (const double* const y, int n);
29
30   ~CubicSplineInterpolator ();
31
32   double interpolate (double x);
33 };
34
35
36 class CubicPolyInterpolator {
37 private:
38   const double* const m_pdY;
39   const int m_n;
40
41 public:
42   CubicPolyInterpolator (const double* const y, int n);
43
44   ~CubicPolyInterpolator ();
45
46   double interpolate (double x);
47 };
48
49
50 template<class T>
51 class BilinearInterpolator {
52 private:
53   T** const m_ppMatrix;
54   const int m_nx;
55   const int m_ny;
56
57 public:
58   BilinearInterpolator (T** ppMatrix, unsigned int nx, unsigned int ny)
59   : m_ppMatrix(ppMatrix), m_nx(nx), m_ny(ny)
60   {}
61
62   T interpolate (double dXPos, double dYPos)
63 {
64   int iFloorX = static_cast<int>(floor(dXPos));
65   int iFloorY = static_cast<int>(floor (dYPos));
66   double dXFrac = dXPos - iFloorX;
67   double dYFrac = dYPos - iFloorY;
68
69   T result = 0;
70
71   if (iFloorX < 0 || iFloorY < 0 || iFloorX > m_nx-1 || iFloorY > m_ny-1)
72     result = 0;
73   else if (iFloorX == m_nx - 1 && iFloorY == m_ny - 1)
74       result = static_cast<T>(m_ppMatrix[m_nx-1][m_ny-1]);
75   else if (iFloorX == m_nx - 1)
76     result = static_cast<T>(m_ppMatrix[iFloorX][iFloorY] + dYFrac * (m_ppMatrix[iFloorX][iFloorY+1] - m_ppMatrix[iFloorX][iFloorY]));
77     else if (iFloorY == m_ny - 1)
78       result = static_cast<T>(m_ppMatrix[iFloorX][iFloorY] + dXFrac * (m_ppMatrix[iFloorX+1][iFloorY] - m_ppMatrix[iFloorX][iFloorY]));
79   else
80     result = static_cast<T>
81       ((1 - dXFrac) * (1 - dYFrac) * m_ppMatrix[iFloorX][iFloorY] +
82        dXFrac * (1 - dYFrac) * m_ppMatrix[iFloorX+1][iFloorY] +
83        dYFrac * (1 - dXFrac) * m_ppMatrix[iFloorX][iFloorY+1] +
84        dXFrac * dYFrac * m_ppMatrix[iFloorX+1][iFloorY+1]);
85
86   return result;
87 }
88     };
89
90
91 template<class T>
92 class BilinearPolarInterpolator {
93 private:
94   T** const m_ppMatrix;
95   const int m_nAngle;
96   const int m_nPos;
97   int m_nCenterPos;
98
99 public:
100   BilinearPolarInterpolator (T** ppMatrix, unsigned int nAngle,
101                              unsigned int nPos)
102   : m_ppMatrix(ppMatrix), m_nAngle(nAngle), m_nPos(nPos)
103   {
104     if (m_nPos %2)
105       m_nCenterPos = (m_nPos - 1) / 2;
106     else
107       m_nCenterPos = m_nPos / 2;
108   }
109
110   T interpolate (double dAngle, double dPos)
111 {
112   int iFloorAngle = static_cast<int>(floor(dAngle));
113   int iFloorPos = static_cast<int>(floor (dPos));
114   double dAngleFrac = dAngle - iFloorAngle;
115   double dPosFrac = dPos - iFloorPos;
116
117   T result = 0;
118
119   if (iFloorAngle < -1 || iFloorPos < 0 || iFloorAngle > m_nAngle-1 || iFloorPos > m_nPos-1)
120     result = 0;
121   else if (iFloorAngle == -1 && iFloorPos == m_nPos-1)
122     result = static_cast<T>(m_ppMatrix[0][m_nPos-1] + dAngleFrac * (m_ppMatrix[m_nAngle-1][iFloorPos] - m_ppMatrix[0][iFloorPos]));
123   else if (iFloorAngle == m_nAngle - 1 && iFloorPos == m_nPos-1)
124     result = static_cast<T>(m_ppMatrix[m_nAngle-1][m_nPos-1] + dAngleFrac * (m_ppMatrix[0][iFloorPos] - m_ppMatrix[m_nAngle-1][iFloorPos]));
125   else if (iFloorPos == m_nPos - 1)
126     result = static_cast<T>(m_ppMatrix[iFloorAngle][iFloorPos] + dAngleFrac * (m_ppMatrix[iFloorAngle+1][iFloorPos] - m_ppMatrix[iFloorAngle][iFloorPos]));
127   else {
128     if (iFloorAngle == m_nAngle-1) {
129       int iUpperAngle = 0;
130       int iLowerPos = (m_nPos-1) - iFloorPos;
131       int iUpperPos = (m_nPos-1) - (iFloorPos+1);
132       result = static_cast<T>
133         ((1-dAngleFrac) * (1-dPosFrac) * m_ppMatrix[iFloorAngle][iFloorPos] +
134          dAngleFrac * (1-dPosFrac) * m_ppMatrix[iUpperAngle][iLowerPos] +
135          dPosFrac * (1-dAngleFrac) * m_ppMatrix[iFloorAngle][iFloorPos+1] +
136          dAngleFrac * dPosFrac * m_ppMatrix[iUpperAngle][iUpperPos]);
137     } else if (iFloorAngle == -1) {
138       int iLowerAngle = m_nAngle - 1;
139       int iLowerPos = (m_nPos-1) - iFloorPos;
140       int iUpperPos = (m_nPos-1) - (iFloorPos+1);
141       result = static_cast<T>
142         ((1-dAngleFrac) * (1-dPosFrac) * m_ppMatrix[iLowerAngle][iLowerPos] +
143          dAngleFrac * (1-dPosFrac) * m_ppMatrix[iFloorAngle+1][iFloorPos] +
144          dPosFrac * (1-dAngleFrac) * m_ppMatrix[iLowerAngle][iUpperPos] +
145          dAngleFrac * dPosFrac * m_ppMatrix[iFloorAngle+1][iFloorPos+1]);
146     } else
147       result = static_cast<T>
148         ((1-dAngleFrac) * (1-dPosFrac) * m_ppMatrix[iFloorAngle][iFloorPos] +
149          dAngleFrac * (1-dPosFrac) * m_ppMatrix[iFloorAngle+1][iFloorPos] +
150          dPosFrac * (1-dAngleFrac) * m_ppMatrix[iFloorAngle][iFloorPos+1] +
151          dAngleFrac * dPosFrac * m_ppMatrix[iFloorAngle+1][iFloorPos+1]);
152   }
153   return result;
154 }
155 };
156
157
158 template<class T>
159 class BicubicPolyInterpolator {
160 private:
161   T** const m_ppMatrix;
162   const unsigned int m_nx;
163   const unsigned int m_ny;
164
165 public:
166   BicubicPolyInterpolator (T** ppMatrix, unsigned int nx, unsigned int ny)
167   : m_ppMatrix(ppMatrix), m_nx(nx), m_ny(ny)
168   {}
169
170   T interpolate (double dXPos, double dYPos)
171   {
172     // int iFloorX = static_cast<int>(floor (dXPos));
173     // int iFloorY = static_cast<int>(floor (dYPos));
174     // double dXFrac = dXPos - iFloorX;
175     // double dYFrac = dYPos - iFloorY;
176
177     T result = 0;
178
179     // Need to add code
180
181     return result;
182   }
183 };
184
185
186 template<class T>
187 class LinearInterpolator {
188 private:
189   T* const m_pX;
190   T* const m_pY;
191   const int m_n;
192   const bool m_bZeroOutsideRange;
193
194 public:
195   LinearInterpolator (T* pY, unsigned int n, bool bZeroOutside = true)
196   : m_pX(0), m_pY(pY), m_n(n), m_bZeroOutsideRange(bZeroOutside)
197   {}
198
199   LinearInterpolator (T* pX, T* pY, unsigned int n, bool bZeroOutside = true)
200   : m_pX(pX), m_pY(pY), m_n(n), m_bZeroOutsideRange(bZeroOutside)
201   {}
202
203   double interpolate (double dX, int* piLastFloor = NULL)
204   {
205     double result = 0;
206
207     if (! m_pX) {
208       if (dX == 0)
209         result = m_pY[0];
210       else if (dX < 0) {
211         if (m_bZeroOutsideRange)
212           result = 0;
213         else
214           result = m_pY[0];
215       } else if (dX == m_n - 1)
216         result = m_pY[m_n-1];
217       else if (dX > m_n - 1) {
218         if (m_bZeroOutsideRange)
219           result = 0;
220         else
221           result = m_pY[m_n - 1];
222       } else {
223        int iFloor = static_cast<int>(floor(dX));
224        result = m_pY[iFloor] + (m_pY[iFloor+1] - m_pY[iFloor]) * (dX - iFloor);
225       }
226     } else {
227       int iLower = -1;
228       int iUpper = m_n;
229       if (piLastFloor && *piLastFloor >= 0 && m_pX[*piLastFloor] < dX)
230         iLower = *piLastFloor;
231
232       while (iUpper - iLower > 1) {
233         int iMiddle = (iUpper + iLower) >> 1;
234         if (dX >= m_pX[iMiddle])
235           iLower = iMiddle;
236         else
237           iUpper = iMiddle;
238       }
239       if (dX == m_pX[0])
240         result = m_pY[0];
241       else if (dX < m_pX[0]) {
242         if (m_bZeroOutsideRange)
243           result = 0;
244         else
245           result = m_pY[0];
246       } else if (dX == m_pX[m_n-1])
247         result = m_pY[m_n-1];
248       else if (dX > m_pX[m_n - 1]) {
249         if (m_bZeroOutsideRange)
250           result = 0;
251         else
252           result = m_pY[m_n - 1];
253       } else {
254         if (iLower < 0 || iLower >= m_n) {
255           sys_error (ERR_SEVERE, "Coordinate out of range [linearInterpolate]");
256           return 0;
257         }
258
259        if (piLastFloor)
260          *piLastFloor = iLower;
261        result = m_pY[iLower] + (m_pY[iUpper] - m_pY[iLower]) * ((dX - m_pX[iLower]) / (m_pX[iUpper] - m_pX[iLower]));
262       }
263     }
264
265     return result;
266   }
267 };
268