VAPoR  0.1
WeightTable.h
Go to the documentation of this file.
1 #ifndef weightTable_h
2 #define weightTable_h
3 namespace VAPoR {
4 // The WeightTable class calculates the weight tables that are used to lookup the interpolation weight that determines the corner x,y indices in user space and
5 // alpha and beta coefficients that are used to interpolate the function value associated with a latitude and longitude grid coordinate.
6 // The table is calculated using an iteration provided by Phil Jones of LANL. It provides alpha, beta, and corner userlon/userlat indices associated with
7 // input lon/lat indices. The input lon/lat indices are the lon/lat grid coordinates for which an interpolated value of a variable is desired.
8 // The resulting ulon/ulat indices correspond to user grid coordinates of the lower left corner of a rectangle whose 4 vertices are used for interpolation.
9 // A weight table must be calculated for all 4 grids (combinations of staggered and unstaggered ulon/ulat grids).
10 // There are a couple of important boundary conditions:
11 // With regional models, the left and bottom edges of the ulon/ulat grid may be 1/2 cell outside the lon/lat grid. In this case the coefficients are used to
12 // extrapolate from the nearest lon/lat cell.
13 // With global models, the left edge of the ulon/ulat grid may wrap around to the right edge. The corresponding ulon/ulat cell will span the left and right
14 // edge of the grid.
15 // The longitude and latitude associated with a ulon/ulat cell must always be valid grid corner indices, even though the floating point lon/lat may be outside the
16 // [0,360] and [-90,90] intervals
17 // No special provision is made for points near the north pole. In that case, the latitude is always less than 90, so a valid rectangle will contain the point in
18 // user ulon/ulat coordinates.
19 //
20 class VDFIOBase;
22 public:
23  //Construct a weight table (initially empty) for a given geo_lat and geo_lon variable.
25  const float *geo_lat, const float *geo_lon,
26  int ny, int nx,
27  const float latexts[2], const float lonexts[2]
28  );
29  virtual ~WeightTable();
30 
31  // Interpolate a 2D or 3D variable to the lon/lat grid, using this weights table
32  // Sourcedata is where the variable data has already been loaded.
33  // Values in the data that are equal to missingValue are mapped to missMap
34  void interp2D(const float* sourceData, float* resultData, float srcMV, float dstMV, const size_t* dims);
35 
36  //Calculate the weights
37  int calcWeights();
38 
39  //Calculate angle that grid makes with latitude line at a particular vertex.
40  float getAngle(int ilon, int ilat) const;
41 
42  const float* getGeoLats() const { return _geo_lat;}
43 
44 private:
45  //Following 2 methods are for debugging:
46  float bestLatLonPolar(int ulon, int ulat);
47  float bestLatLon(int ulon, int ulat);
48 
49  bool MOMBased;
50 
51  //Calculate the weights alpha, beta associated with a point P=(plon,plat), based on rectangle cornered at
52  //user grid vertex nlon, nlat
53  //The point P should be known to be inside the lonlat rectangle associated with the user grid cell cornered at (nlon,nlat)
54  //
55  void findWeight(float plon, float plat, int nlon, int nlat, float* alpha, float *beta);
56  //Alternate version, based on mapping lon,lat to polar coordinates in northern hemisphere
57  void findWeight2(float x, float y, int nlon, int nlat, float* alpha, float *beta);
58  //Check whether a point P=(plon,plat) lies in the quadrilateral defined (in ccw order) by the 4 vertices
59  //ll cornered at user grid vertex (nlon,nlat). Result is negative if point is inside.
60  float testInQuad(float plon, float plat, int nlon, int nlat);
61  //Alternate version, test is based on polar coordinates on the upper hemisphere.
62  float testInQuad2(float x, float y, int nlon, int nlat);
63 
64  float finterp(float A,float B,float th[4]) {return (1.-A)*(1.-B)*th[0]+A*(1.-B)*th[1]+A*B*th[2]+(1.-A)*B*th[3];}
65 
66  float COMDIF2(float th[4],float C){return th[1]-th[0]+C*(th[0]-th[3]+th[2]-th[1]);}
67 
68  float COMDIF4(float th[4],float C) {return th[3]-th[0]+C*(th[0]-th[3]+th[2]-th[1]);}
69 
70  float DET(float A,float B,float th[4],float ph[4]){ return COMDIF2(th,B)*COMDIF4(ph,A) - COMDIF4(th,A)*COMDIF2(ph,B);}
71 
72  float DELT(float theta, float A,float B,float th[4]){
73  return (theta-finterp(A,B,th));
74  }
75  float DELA(float delth,float delph,float th[4],float ph[4],float A,float B){
76  float num = delth*COMDIF4(ph,A) - delph*COMDIF4(th,A);
77  float det = DET(A,B,th,ph);
78  if (det == 0.f) return 1.e30f; //Flag degenerate rectangles
79  return num/det;
80  }
81  float DELB(float delth,float delph,float th[4],float ph[4],float A,float B){
82  float num = delph*COMDIF2(th,B) - delth*COMDIF2(ph,B);
83  float det = DET(A,B,th,ph);
84  if (det == 0.f) return 1.e30f; //Flag degenerate rectangles
85  return num/det;
86  }
87 
88  float errP(float theta,float phi,float A,float B,float th[4],float ph[4]){
89  return abs(theta-finterp(A,B,th)+abs(phi-finterp(A,B,ph)));
90  }
91  //Calculate successive approximations of A and B (i.e. alpha and beta) to be used as weights, in the bilinear approximation
92  // of a point (theta,phi)
93  // where:
94  // theta and phi are the coordinates of the point to be approximated,
95  // th[4] and ph[4] are the x and y corners of the quad containing (theta,phi)
96  //Bilinear approximation is based on work of Phil Jones, LANL
97  float NEWA(float A,float B,float theta,float phi,float th[4],float ph[4]){
98  float delth = DELT(theta,A,B,th);
99  float delph = DELT(phi,A,B,ph);
100  float dela = DELA(delth,delph,th,ph,A,B);
101  if (dela == 1.e30f) return 1.e30f;
102  return (A+dela);
103  }
104  float NEWB(float A,float B,float theta,float phi,float th[4],float ph[4]){
105  float delth = DELT(theta,A,B,th);
106  float delph = DELT(phi,A,B,ph);
107  float delb = DELB(delth,delph,th,ph,A,B);
108  if (delb == 1.e30f) return 1.e30f;
109  return (B+delb);
110  }
111 
112 
113  //Storage for weights:
114  float* _alphas;
115  float* _betas;
116  //cornerLats[j] and cornerLons[j] indicate indices of lower-left corner of user coordinate rectangle that contains
117  // the lon/lat point indexed by "j".
118  int* _cornerLons;
119  int* _cornerLats;
120  //As the table is constructed, keep track of how good is the test. Points near boundary get replaced if a better fit is found.
121  float* _testValues;
122  //Arrays that hold the geo_lat and geo_lon values in the user topo data. To determine the longitude and latitude of
123  //the user grid cell vertex [ilon,ilat], you need to evaluate geo_lon[ilon+ilat*
124  float* _geo_lon;
125  float* _geo_lat;
126  int _nx, _ny; //Grid dimensions
127  float _lonLatExtents[4];
128  float _epsilon, _epsRect;
129  float _deltaLat, _deltaLon;
130  bool _wrapLon, _wrapLat;
131 
132 }; //End WeightTable class
133 
134 }; //End namespace VAPoR
135 #endif
#define VDF_API
Definition: common.h:61
const float * getGeoLats() const
Definition: WeightTable.h:42