X-Git-Url: http://git.kpe.io/?p=ctsim.git;a=blobdiff_plain;f=include%2Finterpolator.h;h=cea4961809cda3300db2c8b227d7639c3d1d734e;hp=def913ec377161f40e86e7765fb24f1faf605cbe;hb=3ea498d51ce4597e9649cd21f155b51175ea0bea;hpb=befd71a7157339b52a0c40359518d5276b25d127 diff --git a/include/interpolator.h b/include/interpolator.h index def913e..cea4961 100644 --- a/include/interpolator.h +++ b/include/interpolator.h @@ -2,7 +2,7 @@ ** This is part of the CTSim program ** Copyright (c) 1983-2001 Kevin Rosenberg ** -** $Id: interpolator.h,v 1.1 2001/02/11 21:57:08 kevin Exp $ +** $Id: interpolator.h,v 1.2 2001/03/21 21:45:31 kevin Exp $ ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License (version 2) as @@ -47,3 +47,114 @@ public: double interpolate (double x); }; + +template +class BilinearInterpolator { +private: + T** const m_ppMatrix; + const unsigned int m_nx; + const unsigned int m_ny; + +public: + BilinearInterpolator (T** ppMatrix, unsigned int nx, unsigned int ny) + : m_ppMatrix(ppMatrix), m_nx(nx), m_ny(ny) + {} + + T interpolate (double dXPos, double dYPos) + { + int iFloorX = floor (dXPos); + int iFloorY = floor (dYPos); + double dXFrac = dXPos - iFloorX; + double dYFrac = dYPos - iFloorY; + + T result = 0; + + if (iFloorX < 0 || iFloorY < 0 || iFloorX > m_nx-1 || iFloorY > m_ny-1) + result = 0; + else if (iFloorX == m_nx - 1 && iFloorY == m_ny - 1) + result = m_ppMatrix[m_nx-1][m_ny-1]; + else if (iFloorX == m_nx - 1) + result = m_ppMatrix[iFloorX][iFloorY] + dYFrac * (m_ppMatrix[iFloorX][iFloorY+1] - m_ppMatrix[iFloorX][iFloorY]); + else if (iFloorY == m_ny - 1) + result = m_ppMatrix[iFloorX][iFloorY] + dXFrac * (m_ppMatrix[iFloorX+1][iFloorY] - m_ppMatrix[iFloorX][iFloorY]); + else + result = (1 - dXFrac) * (1 - dYFrac) * m_ppMatrix[iFloorX][iFloorY] + + dXFrac * (1 - dYFrac) * m_ppMatrix[iFloorX+1][iFloorY] + + dYFrac * (1 - dXFrac) * m_ppMatrix[iFloorX][iFloorY+1] + + dXFrac * dYFrac * m_ppMatrix[iFloorX+1][iFloorY+1]; + + return result; + } +}; + + +template +class LinearInterpolator { +private: + T* const m_pY; + T* const m_pX; + const unsigned int m_n; + +public: + LinearInterpolator (T* pY, unsigned int n) + : m_pY(pY), m_pX(0), m_n(n) + {} + + LinearInterpolator (T* pY, T* pX, unsigned int n) + : m_pY(pY), m_pX(pX), m_n(n) + {} + + double interpolate (double dX, int* piLastFloor = NULL) + { + double result = 0; + + if (! m_pX) { + if (dX == 0) + result = m_pY[0]; + else if (dX < 0) + result = 0; + else if (dX == m_n - 1) + result = m_pY[m_n-1]; + else if (dX > m_n - 1) + result = 0; + else { + int iFloor = floor(dX); + result = m_pY[iFloor] + (m_pY[iFloor+1] - m_pY[iFloor]) * (dX - iFloor); + } + } else { + int iLower = -1; + int iUpper = m_n; + if (piLastFloor && *piLastFloor >= 0 && m_pX[*piLastFloor] < dX) + iLower = *piLastFloor; + + while (iUpper - iLower > 1) { + int iMiddle = (iUpper + iLower) >> 1; + if (dX >= m_pX[iMiddle]) + iLower = iMiddle; + else + iUpper = iMiddle; + } + if (dX == m_pX[0]) + result = m_pY[0]; + else if (dX < m_pX[0]) + result = 0; + else if (dX == m_pX[m_n-1]) + result = m_pY[m_n-1]; + else if (dX > m_pX[m_n-1]) + result = 0; + else { + if (iLower < 0 || iLower >= m_n) { + sys_error (ERR_SEVERE, "Coordinate out of range [linearInterpolate]"); + return 0; + } + + if (piLastFloor) + *piLastFloor = iLower; + result = m_pY[iLower] + (m_pY[iUpper] - m_pY[iLower]) * ((dX - m_pX[iLower]) / (m_pX[iUpper] - m_pX[iLower])); + } + } + + return result; + } +}; +