Grid Interpolation
gridInterp.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <iostream>
4 #include <fstream>
5 #include <sstream>
6 #include <vector>
7 #include <limits>
8 #include <cmath>
9 
10 namespace GRID_INTERP{
11 
18  enum class METHOD{LINEAR,
19  NEAREST,
20  IDW,
22  };
23 
31  enum class TYPE{GRID,
32  LAYER,
34  };
35 
47  class axis{
48  public:
50  axis(){};
58  void setAxis(double origin, double dx, int N);
65  void setAxis(std::vector<double> &x_in);
79  void findIIT(double x_in, int &i1, int &i2, double &t)const;
80 
99  void dataFromFile(std::string filename);
100 
102  void reset();
103 
105  double operator()(int i)const;
106 
109  int last()const;
110 
111  private:
113  std::vector<double> x;
115  int N = 0;
117  double origin = 0.0;
119  double dx = 0.0;
121  bool bConst = false;
126  void findCell(int &i, int &ii, const double x)const;
127  };
128 
129  void axis::reset(){
130  x.clear();
131  origin = 0.0;
132  dx = 0.0;
133  bConst = false;
134  N = 0;
135  }
136  double axis::operator()(int i)const{
137  return x[i];
138  }
139  int axis::last()const{
140  return x.size()-1;
141  }
142 
143  void axis::setAxis(double origin_in, double dx_in, int n){
144  x.clear();
145  for(int i = 0; i < n; i++){
146  x.push_back(origin_in + static_cast<double>(i)*dx_in);
147  }
148  bConst = true;
149  origin = origin_in;
150  dx = dx_in;
151  N = x.size() - 1;
152  }
153 
154  void axis::setAxis(std::vector<double> &x_in){
155  x = x_in;
156  N = x.size() - 1;
157  }
158 
159  void axis::findCell(int &i, int &ii, double x_in)const{
160  switch (bConst)
161  {
162  case true:
163  {
164  i = static_cast<int>((x_in - origin)/dx);
165  ii = i + 1;
166  }
167  break;
168  default:
169  {
170  int mid = (i + ii)/2;
171  if (x_in <= x[mid])
172  ii = mid;
173  else
174  i = mid;
175 
176  if (ii - i <= 1)
177  return;
178  else
179  findCell(i, ii, x_in);
180  }
181  break;
182  }
183  }
184 
185  void axis::findIIT(double x_in, int &i1, int &i2, double &t)const{
186  if (x_in <= x[0]){
187  i1 = 0;
188  i2 = 0;
189  t = 0.0;
190  return;
191  }
192  if (x_in >= x[N]){
193  i1 = N;
194  i2 = N;
195  t = 1.0;
196  return;
197  }
198  i1 = 0;
199  i2 = N;
200  findCell(i1, i2, x_in);
201  t = (x_in - x[i1])/(x[i2] - x[i1]);
202  }
203 
204 
205  void axis::dataFromFile(std::string filename){
206  std::ifstream datafile(filename.c_str());
207  if (!datafile.good()) {
208  std::cout << "Can't open the file: " << filename << std::endl;
209  }
210  else{
211  int Nticks;
212  std::string line, tmp;
213  getline(datafile, line);
214  {
215  std::istringstream inp(line.c_str());
216  inp >> tmp;
217 
218  if (tmp.compare("CONST") == 0)
219  bConst = true;
220  else
221  bConst = false;
222 
223  inp >> Nticks;
224  }
225 
226  if (bConst){
227  getline(datafile, line);
228  std::istringstream inp(line.c_str());
229  inp >> origin;
230  inp >> dx;
231  setAxis(origin, dx, Nticks);
232  }
233  else{
234  x.clear();
235  double xx;
236  for (int i = 0; i < Nticks; i++){
237  getline(datafile, line);
238  std::istringstream inp(line.c_str());
239  inp >> xx;
240  x.push_back(xx);
241  }
242  N = x.size() - 1;
243  }
244  datafile.close();
245  }
246  }
247 
248 
256  class GridValues{
257  public:
261  double operator()(int l, int r, int c)const;
263  double operator()(int r, int c)const;
265  double operator()(int c)const;
269  void resize(int nl, int nr, int nc);
270  // sets the value of the l layer, r row and c column with the value v_in
271  void set(int l, int r, int c, double v_in);
274  void reset();
276  int nx()const;
278  int ny()const;
280  int nz()const;
281  private:
282  std::vector<std::vector<std::vector<double>>> v;
283  };
284 
285  double GridValues::operator()(int l, int r, int c)const{
286  return v[l][r][c];
287  }
288  double GridValues::operator()(int r, int c)const{
289  return v[0][r][c];
290  }
291  double GridValues::operator()(int c)const{
292  return v[0][0][c];
293  }
294  void GridValues::resize(int nl, int nr, int nc){
295  v.clear();
296  //std::vector<double>(nc,0);
297  //std::vector<std::vector<double>>(nr, std::vector<double>(nc,0));
298  v.resize(nl,std::vector<std::vector<double>>(nr, std::vector<double>(nc,0)));
299  }
300  void GridValues::set(int l, int r, int c, double v_in){
301  v[l][r][c] = v_in;
302  }
303 
305  v.clear();
306  }
307 
308  int GridValues::nx()const{
309  return v[0][0].size();
310  }
311  int GridValues::ny()const{
312  return v[0].size();
313  }
314  int GridValues::nz()const{
315  return v.size();
316  }
317 
325  template<int dim>
326  class interp{
327  public:
328  // The constructor resets everything and allocates space for the axis.
329  interp();
330 
339  double interpolate(double x, double y = 0, double z = 0)const;
349  void setAxis(int idim, std::vector<double> &x_in);
358  void setAxis(int idim, double origin_in, double dx_in, int n);
360 
365  void setMethod(METHOD method_in);
366 
396  void getDataFromFile(std::string filename);
397 
413  void setValues(int l, int r, int c, double v_in);
416  void setElevation(int l, int r, int c, double v_in);
417 
419  void reset();
420 
421  private:
423  std::vector<axis> a;
431  double interp1D(double x)const;
433  double interp2D(double x, double y)const;
435  double interp3D(double x, double y, double z)const;
438  //void cellLinearcorrect(int idim, double x, int &i1, int &i2, double &x1, double &x2)const;
439  double translateX = 0.0;
440  double translateY = 0.0;
441  double rotate = 0.0;
442  double cosTH;
443  double sinTH;
444  bool bPreTransform = false;
445  };
446 
447 
448  template<int dim>
450  a.clear();
451  a.resize(dim);
452  }
453 
454  template<int dim>
456  for(int idim = 0; idim < dim; ++ idim)
457  a[idim].reset();
458  v.reset();
459  elev.reset();
460  //mode = MODE::INVALID_MODE;
461  method = METHOD::INVALID_METHOD;
462  }
463 
464  template <int dim>
465  void interp<dim>::setAxis(int idim, std::vector<double> &x_in){
466  if (idim < dim)
467  a[idim].setAxis(x_in);
468  }
469 
470  template <int dim>
471  void interp<dim>::setAxis(int idim, double origin_in, double dx_in, int n){
472  if (idim < dim)
473  a[idim].setAxis(origin_in, dx_in, n);
474  }
475 
476  template<int dim>
477  void interp<dim>::setValues(int l, int r, int c, double v_in){
478  v.set(l,r,c,v_in);
479  }
480 
481  template <int dim>
482  void interp<dim>::setElevation(int l, int r, int c, double v_in){
483  elev.set(l, r, c, v_in);
484  }
485 
486  template<int dim>
488  //mode = mode_in;
489  method = method_in;
490  }
491 
492  template <int dim>
493  void interp<dim>::getDataFromFile(std::string filename){
494  std::ifstream datafile(filename.c_str());
495  if (!datafile.good()) {
496  std::cout << "Can't open the file: " << filename << std::endl;
497  }
498  else{
499  //MODE md;
500  METHOD mthd;
501  std::string line, tmp;
502  std::vector<int> dims;
503 
504  getline(datafile, line);
505  {// METHOD NX NY NZ
506  std::istringstream inp(line.c_str());
507  inp >> tmp;
508  if (tmp.compare("GRIDDED") == 0){
509  // If the first line is GRIDDED ignore it and read the next line
510  getline(datafile, line);
511  inp.clear();
512  inp.str(line.c_str());
513  inp >> tmp;
514  }
515 
516  if (tmp.compare("LINEAR") == 0)
517  mthd = METHOD::LINEAR;
518  else if (tmp.compare("NEAREST") == 0)
519  mthd = METHOD::NEAREST;
520  else
521  mthd = METHOD::INVALID_METHOD;
522  int d;
523  for(int idim = 0; idim < dim; ++idim){
524  inp >> d;
525  dims.push_back(d);
526  }
527 
528  {// Attempt to read transformation parameters
529  inp >> translateX;
530  inp >> translateY;
531  inp >> rotate;
532  if (std::abs(translateX) > 0.000001 || std::abs(translateY) > 0.000001 || std::abs(rotate) > 0.000001){
533  bPreTransform = true;
534  // Calculate the rotation values
535  double pi = 4*std::atan(1);
536  cosTH = std::cos(rotate * pi/180.0);
537  sinTH = std::sin(rotate * pi/180.0);
538  }
539  }
540 
541  if (dim == 1)
542  v.resize(1,1,dims[0]);
543  else if (dim == 2)
544  v.resize(1,dims[1],dims[0]);
545  else if (dim == 3)
546  v.resize(dims[2], dims[1], dims[0]);
547  }
548 
549  getline(datafile, line);
550  {// FILEX, FILEY, FILEZ
551  std::istringstream inp(line.c_str());
552  for(int i = 0; i < dim; ++i){
553  inp >> tmp;
554  a[i].dataFromFile(tmp);
555  }
556  }
557  if (dim == 1){
558  double vv;
559  for (int i = 0; i < dims[0]; ++i){
560  getline(datafile, line);
561  std::istringstream inp(line.c_str());
562  inp >> vv;
563  v.set(0,0,i,vv);
564  }
565  }
566  else{
567  int nz = 1;
568  int ny, nx;
569  if (dim == 2){
570  nx = dims[0];
571  ny = dims[1];
572  }
573  else if (dim == 3){
574  nx = dims[0];
575  ny = dims[1];
576  nz = dims[2];
577 
578  }
579  double vv;
580  for (int k = 0; k < nz; ++k)
581  for (int i = 0; i < ny; ++i){
582  getline(datafile, line);
583  std::istringstream inp(line.c_str());
584  for (int j = 0; j < nx; ++j){
585  inp >> vv;
586  v.set(k, i, j, vv);
587  }
588  }
589  }
590  setMethod(mthd);
591  datafile.close();
592  }
593  }
594 
595  template<int dim>
596  double interp<dim>::interpolate(double x, double y, double z)const{
597  if (bPreTransform){
598  x = x + translateX;
599  y = y + translateY;
600  x = x * cosTH - y * sinTH;
601  x = x * sinTH + y * cosTH;
602  }
603  double outcome;
604  switch (dim)
605  {
606  case 1:
607  outcome = interp1D(x);
608  break;
609  case 2:
610  outcome = interp2D(x,y);
611  break;
612  case 3:
613  outcome = interp3D(x,y,z);
614  break;
615  default:
616  outcome = std::numeric_limits<double>::quiet_NaN();
617  break;
618  }
619  return outcome;
620  }
621 
622  template<int dim>
623  double interp<dim>::interp1D(double x)const{
624  double outcome;
625  int i1, i2;
626  double t;
627  a[0].findIIT(x,i1, i2, t);
628  switch (method)
629  {
630  case METHOD::LINEAR:
631  outcome = v(i1)*(1-t) + v(i2)*t;
632  break;
633  case METHOD::NEAREST:
634  if (std::abs(a[0](i1) - x) <= std::abs(a[0](i2) - x))
635  outcome = v(i1);
636  else
637  outcome = v(i2);
638  break;
639  default:
640  outcome = std::numeric_limits<double>::quiet_NaN();
641  break;
642  }
643  return outcome;
644  }
645 
646 
647  template<int dim>
648  double interp<dim>::interp2D(double x, double y)const{
649  double outcome;
650  int i1, i2, j1, j2;
651  double tx, ty;
652  a[0].findIIT(x, j1, j2, tx);
653  a[1].findIIT(y, i1, i2, ty);
654 
655  switch (method)
656  {
657  case METHOD::LINEAR:
658  {
659  double y1 = v(i1, j1)*(1-tx) + v(i1, j2)*tx;
660  double y2 = v(i2, j1)*(1-tx) + v(i2, j2)*tx;
661  outcome = y1*(1-ty) + y2*ty;
662 
663  }
664  break;
665  case METHOD::NEAREST:
666  {
667  int i, j;
668  if (std::abs(a[0](j1) - x) <= std::abs(a[0](j2) - x))
669  j = j1;
670  else
671  j = j2;
672 
673  if (std::abs(a[1](i1) - y) <= std::abs(a[1](i2) - y))
674  i = i1;
675  else
676  i = i2;
677  outcome = v(i,j);
678  }
679  break;
680  default:
681  break;
682  }
683  return outcome;
684  }
685 
686  template<int dim>
687  double interp<dim>::interp3D(double x, double y, double z)const{
688  int i1, i2, j1, j2, k1, k2;
689  double tx, ty, tz;
690  a[0].findIIT(x, j1, j2, tx);
691  a[1].findIIT(y, i1, i2, ty);
692  a[2].findIIT(z, k1, k2, tz);
693 
694  switch (method)
695  {
696  case METHOD::LINEAR:
697  {
698  double z1y1 = v(k1, i1, j1)*(1-tx) + v(k1, i1, j2)*tx;
699  double z1y2 = v(k1, i2, j1)*(1-tx) + v(k1, i2, j2)*tx;
700  double z1 = z1y1*(1-ty) + z1y2*ty;
701 
702  double z2y1 = v(k2, i1, j1)*(1-tx) + v(k2, i1, j2)*tx;
703  double z2y2 = v(k2, i2, j1)*(1-tx) + v(k2, i2, j2)*tx;
704  double z2 = z2y1*(1-ty) + z2y2*ty;
705 
706  return z1*(1-tz) + z2*tz;
707  }
708  break;
709  case METHOD::NEAREST:
710  {
711  int i, j, k;
712  if (std::abs(a[0](j1) - x) <= std::abs(a[0](j2) - x))
713  j = j1;
714  else
715  j = j2;
716 
717  if (std::abs(a[1](i1) - y) <= std::abs(a[1](i2) - y))
718  i = i1;
719  else
720  i = i2;
721  if (std::abs(a[2](k1) - y) <= std::abs(a[2](k2) - y))
722  k = k1;
723  else
724  k = k2;
725  return v(k, i, j);
726 
727  }
728  break;
729  default:
730  {
731  return -99999999.9;
732  break;
733  }
734  }
735  }
736 
738  void writeCoordsValues(std::string filename, std::vector<std::vector<double>> &coords, std::vector<double> &v){
739  std::ofstream out_file;
740  out_file.open(filename.c_str());
741  for (unsigned int i = 0; i < coords.size(); i++){
742  for (unsigned j = 0; j < coords[i].size(); j++){
743  out_file << coords[i][j] << " ";
744  }
745  out_file << v[i] << std::endl;
746  }
747  out_file.close();
748  }
749 }
750 
void getDataFromFile(std::string filename)
Get the Data From File object.
Definition: gridInterp.h:493
int nx() const
returns the number of columns or values in the x direction
Definition: gridInterp.h:308
int last() const
Definition: gridInterp.h:139
GridValues()
Empty constructor.
Definition: gridInterp.h:259
std::vector< std::vector< std::vector< double > > > v
Definition: gridInterp.h:282
void reset()
Resets the class to the empty state.
Definition: gridInterp.h:455
The axis class is a container for axis tick values.
Definition: gridInterp.h:47
std::vector< axis > a
A vector of axis objects.
Definition: gridInterp.h:423
void writeCoordsValues(std::string filename, std::vector< std::vector< double >> &coords, std::vector< double > &v)
This is a utility function which is used to print the results of the interpolation to a file so that ...
Definition: gridInterp.h:738
Definition: gridInterp.h:10
double interp3D(double x, double y, double z) const
The interpolate method will call this when dim is 3.
Definition: gridInterp.h:687
double operator()(int l, int r, int c) const
Access operator in 3D.
Definition: gridInterp.h:285
void setValues(int l, int r, int c, double v_in)
Set the values of the iterpolation.
Definition: gridInterp.h:477
axis()
The constructor does absolutely nothing.
Definition: gridInterp.h:50
void findIIT(double x_in, int &i1, int &i2, double &t) const
Finds the lower and upper ids that enclose the input value #x_in. Also returns the parametric value t...
Definition: gridInterp.h:185
GridValues v
The container for the values that are used in the interpolation.
Definition: gridInterp.h:425
void set(int l, int r, int c, double v_in)
Definition: gridInterp.h:300
double interp1D(double x) const
The interpolate method will call this when dim is 1.
Definition: gridInterp.h:623
void setMethod(METHOD method_in)
sets the method
Definition: gridInterp.h:487
GridValues elev
In 3D this holds the layer elevation information.
Definition: gridInterp.h:427
double cosTH
Definition: gridInterp.h:442
double interpolate(double x, double y=0, double z=0) const
This is the method to call to do the interpolation.
Definition: gridInterp.h:596
void reset()
Definition: gridInterp.h:304
void dataFromFile(std::string filename)
Reads the axis data from file.
Definition: gridInterp.h:205
METHOD
Enumeration for the interpolation methods.
Definition: gridInterp.h:18
TYPE
The interpolation type it is used only in 3D. For 1 and 2 D it is ignored. The normal type is when in...
Definition: gridInterp.h:31
void setAxis(double origin, double dx, int N)
Set the Axis tick values when the space between the ticks is constant.
Definition: gridInterp.h:143
void setElevation(int l, int r, int c, double v_in)
Definition: gridInterp.h:482
int nz() const
returns the number of layers or values in the z direction
Definition: gridInterp.h:314
void resize(int nl, int nr, int nc)
Definition: gridInterp.h:294
std::vector< double > x
is the vector that containts the tick values
Definition: gridInterp.h:113
void reset()
Delets all data and resest the axis object to its original state.
Definition: gridInterp.h:129
interp()
Definition: gridInterp.h:449
void findCell(int &i, int &ii, const double x) const
Definition: gridInterp.h:159
double operator()(int i) const
accessor for the i element of the axis
Definition: gridInterp.h:136
void setAxis(int idim, std::vector< double > &x_in)
Set the Axis object.
Definition: gridInterp.h:465
Main interpolation class.
Definition: gridInterp.h:326
int ny() const
returns the number of rows or values in the y direction
Definition: gridInterp.h:311
double interp2D(double x, double y) const
The interpolate method will call this when dim is 2.
Definition: gridInterp.h:648
double sinTH
Definition: gridInterp.h:443
This is a container class for the values.
Definition: gridInterp.h:256