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