// // Author: Joshua Cohen // Copyright 2017 // #include #include #include #include #include #include #include #include "Interpolator.h" #include "Constants.h" using std::complex; using std::invalid_argument; using std::max; using std::min; using std::string; using std::to_string; using std::vector; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * template U Interpolator::bilinear(double x, double y, vector> &z) { int x1 = floor(x); int x2 = ceil(x); int y1 = ceil(y); int y2 = floor(y); auto q11 = z[y1-1][x1-1]; auto q12 = z[y2-1][x1-1]; auto q21 = z[y1-1][x2-1]; auto q22 = z[y2-1][x2-1]; if ((y1 == y2) && (x1 == x2)) return q11; else if (y1 == y2) return (static_cast((x2 - x) / (x2 - x1)) * q11) + (static_cast((x - x1) / (x2 - x1)) * q21); else if (x1 == x2) return (static_cast((y2 - y) / (y2 - y1)) * q11) + (static_cast((y - y1) / (y2 - y1)) * q12); else { return ((q11 * static_cast((x2 - x) * (y2 - y))) / static_cast((x2 - x1) * (y2 - y1))) + ((q21 * static_cast((x - x1) * (y2 - y))) / static_cast((x2 - x1) * (y2 - y1))) + ((q12 * static_cast((x2 - x) * (y - y1))) / static_cast((x2 - x1) * (y2 - y1))) + ((q22 * static_cast((x - x1) * (y - y1))) / static_cast((x2 - x1) * (y2 - y1))); } } template complex Interpolator::bilinear(double,double,vector>>&); template complex Interpolator::bilinear(double,double,vector>>&); template double Interpolator::bilinear(double,double,vector>&); template float Interpolator::bilinear(double,double,vector>&); // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * template U Interpolator::bicubic(double x, double y, vector> &z) { vector> wt = {{1.0, 0.0,-3.0, 2.0, 0.0, 0.0, 0.0, 0.0,-3.0, 0.0, 9.0,-6.0, 2.0, 0.0,-6.0, 4.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.0, 0.0,-9.0, 6.0,-2.0, 0.0, 6.0,-4.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 9.0,-6.0, 0.0, 0.0,-6.0, 4.0}, {0.0, 0.0, 3.0,-2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0- 9.0, 6.0, 0.0, 0.0, 6.0,-4.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0,-3.0, 2.0,-2.0, 0.0, 6.0,-4.0, 1.0, 0.0,-3.0, 2.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,-1.0, 0.0, 3.0,-2.0, 1.0, 0.0,-3.0, 2.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,-3.0, 2.0, 0.0, 0.0, 3.0,-2.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.0,-2.0, 0.0, 0.0,-6.0, 4.0, 0.0, 0.0, 3.0,-2.0}, {0.0, 1.0,-2.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0,-3.0, 6.0,-3.0, 0.0, 2.0,-4.0, 2.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.0,-6.0, 3.0, 0.0,-2.0, 4.0,-2.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,-3.0, 3.0, 0.0, 0.0, 2.0,-2.0}, {0.0, 0.0,-1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.0,-3.0, 0.0, 0.0,-2.0, 2.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0,-2.0, 1.0, 0.0,-2.0, 4.0,-2.0, 0.0, 1.0,-2.0, 1.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,-1.0, 2.0,-1.0, 0.0, 1.0,-2.0, 1.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0,-1.0, 0.0, 0.0,-1.0, 1.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0,-1.0, 1.0, 0.0, 0.0, 2.0,-2.0, 0.0, 0.0,-1.0, 1.0}}; int x1 = floor(x) - 1; int x2 = ceil(x) - 1; int y1 = floor(y) - 1; int y2 = ceil(y) - 1; vector zz = {z[y1][x1], z[y1][x2], z[y2][x2], z[y2][x1]}; vector dzdx = {(z[y1][x1+1] - z[y1][x1-1]) / static_cast(2.0), (z[y1][x2+1] - z[y1][x2-1]) / static_cast(2.0), (z[y2][x2+1] - z[y2][x2-1]) / static_cast(2.0), (z[y2][x1+1] - z[y2][x1-1]) / static_cast(2.0)}; vector dzdy = {(z[y1+1][x1] - z[y1-1][x1]) / static_cast(2.0), (z[y1+1][x2+1] - z[y1-1][x2]) / static_cast(2.0), (z[y2+1][x2+1] - z[y2-1][x2]) / static_cast(2.0), (z[y2+1][x1+1] - z[y2-1][x1]) / static_cast(2.0)}; vector dzdxy = {static_cast(.25)*(z[y1+1][x1+1] - z[y1-1][x1+1] - z[y1+1][x1-1] + z[y1-1][x1-1]), static_cast(.25)*(z[y1+1][x2+1] - z[y1-1][x2+1] - z[y1+1][x2-1] + z[y1-1][x2-1]), static_cast(.25)*(z[y2+1][x2+1] - z[y2-1][x2+1] - z[y2+1][x2-1] + z[y2-1][x2-1]), static_cast(.25)*(z[y2+1][x1+1] - z[y2-1][x1+1] - z[y2+1][x1-1] + z[y2-1][x1-1])}; vector q(16); for (int i=0; i<4; i++) { q[i] = zz[i]; q[i+4] = dzdx[i]; q[i+8] = dzdy[i]; q[i+12] = dzdxy[i]; } vector c(16,0.); for (int i=0; i<16; i++) { for (int j=0; j<16; j++) { c[i] += static_cast(wt[i][j]) * q[j]; } } U t = x - x1; U u = y - y1; U ret = 0.; for (int i=3; i>=0; i--) ret = (t * ret) + c[IDX1D(i,0,4)] + (((((c[IDX1D(i,3,4)] * u) + c[IDX1D(i,2,4)]) * u) + c[IDX1D(i,1,4)]) * u); return ret; } template complex Interpolator::bicubic(double,double,vector>>&); template complex Interpolator::bicubic(double,double,vector>>&); template double Interpolator::bicubic(double,double,vector>&); template float Interpolator::bicubic(double,double,vector>&); // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * void Interpolator::sinc_coef(double beta, double relfiltlen, int decfactor, double pedestal, int weight, int &intplength, int &filtercoef, vector &filter) { intplength = round(relfiltlen / beta); filtercoef = intplength * decfactor; double wgthgt = 1. - (pedestal / 2.); double soff = (filtercoef - 1.) / 2.; double wgt, s, fct; for (int i=0; i U Interpolator::sinc_eval(vector &arr, vector &intarr, int idec, int ilen, int intp, double frp, int nsamp) { U ret = 0.; if ((intp >= (ilen-1)) && (intp < nsamp)) { int ifrc = min(max(0, int(frp*idec)), idec-1); for (int i=0; i(intarr[IDX1D(ifrc,i,ilen)]); } return ret; } template complex Interpolator::sinc_eval(vector>&,vector&,int,int,int,double,int); template complex Interpolator::sinc_eval(vector>&,vector&,int,int,int,double,int); template complex Interpolator::sinc_eval(vector>&,vector&,int,int,int,double,int); template complex Interpolator::sinc_eval(vector>&,vector&,int,int,int,double,int); template double Interpolator::sinc_eval(vector&,vector&,int,int,int,double,int); template double Interpolator::sinc_eval(vector&,vector&,int,int,int,double,int); template float Interpolator::sinc_eval(vector&,vector&,int,int,int,double,int); template float Interpolator::sinc_eval(vector&,vector&,int,int,int,double,int); // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * template U Interpolator::sinc_eval_2d(vector> &arrin, vector &intarr, int idec, int ilen, int intpx, int intpy, double frpx, double frpy, int xlen, int ylen) { U ret(0.); if ((intpx >= (ilen-1)) && (intpx < xlen) && (intpy >= (ilen-1)) && (intpy < ylen)) { int ifracx = min(max(0, int(frpx*idec)), idec-1); int ifracy = min(max(0, int(frpy*idec)), idec-1); for (int i=0; i(intarr[IDX1D(ifracx,i,ilen)]) * static_cast(intarr[IDX1D(ifracy,j,ilen)]); } } } return ret; } template complex Interpolator::sinc_eval_2d(vector>>&,vector&,int,int,int,int,double,double,int,int); template complex Interpolator::sinc_eval_2d(vector>>&,vector&,int,int,int,int,double,double,int,int); template complex Interpolator::sinc_eval_2d(vector>>&,vector&,int,int,int,int,double,double,int,int); template complex Interpolator::sinc_eval_2d(vector>>&,vector&,int,int,int,int,double,double,int,int); template double Interpolator::sinc_eval_2d(vector>&,vector&,int,int,int,int,double,double,int,int); template double Interpolator::sinc_eval_2d(vector>&,vector&,int,int,int,int,double,double,int,int); template float Interpolator::sinc_eval_2d(vector>&,vector&,int,int,int,int,double,double,int,int); template float Interpolator::sinc_eval_2d(vector>&,vector&,int,int,int,int,double,double,int,int); // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * float Interpolator::interp_2d_spline(int order, int nx, int ny, vector> &z, double x, double y) { // Error checking if ((order < 3) || (order > 20)) { string errstr = "Interpolator::interp_2d_spline - Spline order must be between 3 and 20 (received "+to_string(order)+")"; throw invalid_argument(errstr); } int i0, j0; if ((order % 2) != 0) { i0 = y - .5; j0 = x - .5; } else { i0 = y; j0 = x; } i0 = i0 - (order / 2) + 1; j0 = j0 - (order / 2) + 1; vector A(order), R(order), Q(order), HC(order); int indi, indj; for (int i=1; i<=order; i++) { indi = min(max((i0+i), 1), ny); for (int j=1; j<=order; j++) { indj = min(max((j0+j), 1), nx); A[j-1] = z[indi-1][indj-1]; } initSpline(A,order,R,Q); HC[i-1] = spline((x-j0),A,order,R); } initSpline(HC,order,R,Q); return static_cast(spline((y-i0),HC,order,R)); } void initSpline(vector &Y, int n, vector &R, vector &Q) { Q[0] = 0.; R[0] = 0.; for (int i=2; i=2; i--) R[i-1] = (Q[i-1] * R[i]) + R[i-1]; } double spline(double x, vector &Y, int n, vector &R) { if (x < 1.) return Y[0] + ((x - 1.) * (Y[1] - Y[0] - (R[1] / 6.))); else if (x > n) return Y[n-1] + ((x - n) * (Y[n-1] - Y[n-2] + (R[n-2] / 6.))); else { int j = floor(x); auto xx = x - j; auto t0 = Y[j] - Y[j-1] - (R[j-1] / 3.) - (R[j] / 6.); auto t1 = xx * ((R[j-1] / 2.) + (xx * ((R[j] - R[j-1]) / 6))); return Y[j-1] + (xx * (t0 + t1)); } } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * double Interpolator::quadInterpolate(vector &x, vector &y, double xintp) { auto xin = xintp - x[0]; vector x1(3), y1(3); for (int i=0; i<3; i++) { x1[i] = x[i] - x[0]; y1[i] = y[i] - y[0]; } double a = ((-y1[1] * x1[2]) + (y1[2] * x1[1])) / ((-x1[2] * x1[1] * x1[1]) + (x1[1] * x1[2] * x1[2])); double b = (y1[1] - (a * x1[1] * x1[1])) / x1[1]; return y[0] + (a * xin * xin) + (b * xin); } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * double Interpolator::akima(int nx, int ny, vector> &z, double x, double y) { vector> sx(2,vector(2)), sy(2,vector(2)), sxy(2,vector(2)), e(2,vector(2)); vector m(4); double wx2,wx3,wy2,wy3; int ix = x; int iy = y; wx2 = wx3 = wy2 = wy3 = 0.; for (int ii=0; ii<2; ii++) { int xx = min(max((ix+ii+1),3),(nx-2)) - 1; for (int jj=0; jj<2; jj++) { int yy = min(max((iy+jj+1),3),(ny-2)) - 1; m[0] = z[xx-1][yy] - z[xx-2][yy]; m[1] = z[xx][yy] - z[xx-1][yy]; m[2] = z[xx+1][yy] - z[xx][yy]; m[3] = z[xx+2][yy] - z[xx+1][yy]; if ((abs(m[0] - m[1]) <= DBL_EPSILON) && (abs(m[2] - m[3]) <= DBL_EPSILON)) sx[ii][jj] = 0.5 * (m[1] + m[2]); else { wx2 = abs(m[3] - m[2]); wx3 = abs(m[1] - m[0]); sx[ii][jj] = ((wx2 * m[1]) + (wx3 * m[2])) / (wx2 + wx3); } m[0] = z[xx][yy-1] - z[xx][yy-2]; m[1] = z[xx][yy] - z[xx][yy-1]; m[2] = z[xx][yy+1] - z[xx][yy]; m[3] = z[xx][yy+2] - z[xx][yy+1]; if ((abs(m[0] - m[1]) <= DBL_EPSILON) && (abs(m[2] - m[3]) <= DBL_EPSILON)) sy[ii][jj] = 0.5 * (m[1] + m[2]); else { wy2 = abs(m[3] - m[2]); wy3 = abs(m[1] - m[0]); sy[ii][jj] = ((wy2 * m[1]) + (wy3 * m[2])) / (wy2 + wy3); } e[0][0] = m[1] - z[xx-1][yy] - z[xx-1][yy-1]; e[0][1] = m[2] - z[xx-1][yy+1] - z[xx-1][yy]; e[1][0] = z[xx+1][yy] - z[xx+1][yy-1] - m[1]; e[1][1] = z[xx+1][yy+1] - z[xx+1][yy] - m[2]; if ((abs(wx2) <= DBL_EPSILON) && (abs(wx3) <= DBL_EPSILON)) wx2 = wx3 = 1.; if ((abs(wy2) <= DBL_EPSILON) && (abs(wy3) <= DBL_EPSILON)) wy2 = wy3 = 1.; sxy[ii][jj] = ((wx2 * ((wy2 * e[0][0]) + (wy3 * e[0][1]))) + (wx3 * ((wy2 * e[1][0]) + (wy3 * e[1][1])))) / ((wx2 + wx3) * (wy2 + wy3)); } } vector d(9); d[0] = (z[ix-1][iy-1] - z[ix][iy-1]) + (z[ix][iy] - z[ix-1][iy]); d[1] = (sx[0][0] + sx[1][0]) - (sx[1][1] + sx[0][1]); d[2] = (sy[0][0] - sy[1][0]) - (sy[1][1] - sy[0][1]); d[3] = (sxy[0][0] + sxy[1][0]) + (sxy[1][1] + sxy[0][1]); d[4] = ((2 * sx[0][0]) + sx[1][0]) - (sx[1][1] + (2 * sx[0][1])); d[5] = (2 * (sy[0][0] - sy[1][0])) - (sy[1][1] - sy[0][1]); d[6] = (2 * (sxy[0][0] + sxy[1][0])) + (sxy[1][1] + sxy[0][1]); d[7] = ((2 * sxy[0][0]) + sxy[1][0]) + (sxy[1][1] + (2 * sxy[0][1])); d[8] = (2 * ((2 * sxy[0][0]) + sxy[1][0])) + (sxy[1][1] + (2 * sxy[0][1])); vector poly(16); poly[0] = (2 * ((2 * d[0]) + d[1])) + ((2 * d[2]) + d[3]); poly[1] = -((3 * ((2 * d[0]) + d[1])) + ((2 * d[5]) + d[6])); poly[2] = (2 * (sy[0][0] - sy[1][0])) + (sxy[0][0] + sxy[1][0]); poly[3] = (2 * (z[ix-1][iy-1] - z[ix][iy-1])) + (sx[0][0] + sx[1][0]); poly[4] = -((2 * ((3 * d[0]) + d[4])) + ((3 * d[2]) + d[7])); poly[5] = (3 * ((3 * d[0]) + d[4])) + ((3 * d[5]) + d[8]); poly[6] = -((3 * (sy[0][0] - sy[1][0])) + ((2 * sxy[0][0]) + sxy[1][0])); poly[7] = -((3 * (z[ix-1][iy-1] - z[ix][iy-1])) + ((2 * sx[0][0]) + sx[1][0])); poly[8] = (2 * (sx[0][0] - sx[0][1])) + (sxy[0][0] + sxy[0][1]); poly[9] = -((3 * (sx[0][0] - sx[0][1])) + ((2 * sxy[0][0]) + sxy[0][1])); poly[10] = sxy[0][0]; poly[11] = sx[0][0]; poly[12] = (2 * (z[ix-1][iy-1] - z[ix-1][iy])) + (sy[0][0] + sy[0][1]); poly[13] = -((3 * (z[ix-1][iy-1] - z[ix-1][iy])) + ((2 * sy[0][0]) + sy[0][1])); poly[14] = sy[0][0]; poly[15] = z[ix-1][iy-1]; //return polyvalAkima(int(x),int(y),x,y,poly); m[0] = (((((poly[0] * (y - iy)) + poly[1]) * (y - iy)) + poly[2]) * (y - iy)) + poly[3]; m[1] = (((((poly[4] * (y - iy)) + poly[5]) * (y - iy)) + poly[6]) * (y - iy)) + poly[7]; m[2] = (((((poly[8] * (y - iy)) + poly[9]) * (y - iy)) + poly[10]) * (y - iy)) + poly[11]; m[3] = (((((poly[12] * (y - iy)) + poly[13]) * (y - iy)) + poly[14]) * (y - iy)) + poly[15]; return (((((m[0] * (x - ix)) + m[1]) * (x - ix)) + m[2]) * (x - ix)) + m[3]; }