1 //*******************************************************************
2 //
3 // License:  See top level LICENSE.txt file.
4 //
5 // Author:  Garrett Potts <gpotts@imagelinks.com>
6 //
7 // Description:
8 //*******************************************************************
9 //  $Id: ossimAtCorrGridRemapper.cpp 21631 2012-09-06 18:10:55Z dburken $
10 #include <ossim/imaging/ossimAtCorrGridRemapper.h>
11 #include <ossim/imaging/ossimImageData.h>
12 
13 RTTI_DEF1(ossimAtCorrGridRemapper, "ossimAtCorrGridRemapper", ossimAtCorrRemapper);
14 
15 using namespace std;
16 
ossimAtCorrGridRemapper(ossimObject * owner,ossimImageSource * inputSource,const ossimString & sensorType)17 ossimAtCorrGridRemapper::ossimAtCorrGridRemapper(ossimObject* owner,
18                                                  ossimImageSource* inputSource,
19                                                  const ossimString& sensorType)
20    :ossimAtCorrRemapper(owner, inputSource, sensorType)
21 {
22    theUseInterpolationFlag = true;
23 }
24 
~ossimAtCorrGridRemapper()25 ossimAtCorrGridRemapper::~ossimAtCorrGridRemapper()
26 {
27 }
28 
interpolate(const ossimDpt & pt,int band,double & a,double & b,double & c) const29 void ossimAtCorrGridRemapper::interpolate(const ossimDpt& pt,
30                                           int band,
31                                           double& a,
32                                           double& b,
33                                           double& c)const
34 {
35    if(theGridBounds.pointWithin(pt))
36    {
37       double x = (((double)(pt.x - theUlGridBound.x))/theGridBounds.width())*(theGridSize.x-1);
38       double y = (((double)(pt.y - theUlGridBound.y))/theGridBounds.height())*(theGridSize.y-1);
39 
40       int xidx = (int)x;
41       int yidx = (int)y;
42 
43       double xt = x - xidx;
44       double yt = y - yidx;
45 
46       double va00 = theAGrid[band][yidx][xidx];
47       double va01 = theAGrid[band][yidx][xidx+1];
48       double va11 = theAGrid[band][yidx+1][xidx+1];
49       double va10 = theAGrid[band][yidx+1][xidx];
50       double vb00 = theBGrid[band][yidx][xidx];
51       double vb01 = theBGrid[band][yidx][xidx+1];
52       double vb11 = theBGrid[band][yidx+1][xidx+1];
53       double vb10 = theBGrid[band][yidx+1][xidx];
54       double vc00 = theCGrid[band][yidx][xidx];
55       double vc01 = theCGrid[band][yidx][xidx+1];
56       double vc11 = theCGrid[band][yidx+1][xidx+1];
57       double vc10 = theCGrid[band][yidx+1][xidx];
58 
59       double vaInterpH1 = va00 + (va01-va00)*xt;
60       double vaInterpH2 = va10 + (va11-va10)*xt;
61       double vbInterpH1 = vb00 + (vb01-vb00)*xt;
62       double vbInterpH2 = vb10 + (vb11-vb10)*xt;
63       double vcInterpH1 = vc00 + (vc01-vc00)*xt;
64       double vcInterpH2 = vc10 + (vc11-vc10)*xt;
65 
66       a = vaInterpH1 + (vaInterpH2-vaInterpH1)*yt;
67       b = vbInterpH1 + (vbInterpH2-vbInterpH1)*yt;
68       c = vcInterpH1 + (vcInterpH2-vcInterpH1)*yt;
69    }
70    else
71    {
72       ossimAtCorrRemapper::interpolate(pt,
73                                        band,
74                                        a,
75                                        b,
76                                        c);
77    }
78 }
79 
initialize()80 void ossimAtCorrGridRemapper::initialize()
81 {
82    ossimAtCorrRemapper::initialize();
83 
84    if(theInputConnection)
85    {
86       theGridBounds = theInputConnection->getBoundingRect();
87       theUlGridBound = theGridBounds.ul();
88    }
89    else
90    {
91       theGridBounds.makeNan();
92    }
93 
94    if(!theAGrid.size()||
95       !theBGrid.size()||
96       !theCGrid.size())
97    {
98       theUseInterpolationFlag=false;
99    }
100    setBaseToAverage();
101 }
102 
setGridSize(ossim_uint32 numberOfBands,const ossimIpt & gridSize)103 void ossimAtCorrGridRemapper::setGridSize(ossim_uint32 numberOfBands, const ossimIpt& gridSize)
104 {
105 
106    if((theGridSize!=gridSize)||(numberOfBands != theAGrid.size()))
107    {
108       theAGrid.resize(numberOfBands);
109       theBGrid.resize(numberOfBands);
110       theCGrid.resize(numberOfBands);
111 
112       for(ossim_uint32 b = 0; b < numberOfBands;++b)
113       {
114          theAGrid[b].resize(gridSize.y);
115          theBGrid[b].resize(gridSize.y);
116          theCGrid[b].resize(gridSize.y);
117          for(int r = 0; r < gridSize.y; ++r)
118          {
119             theAGrid[b][r].resize(gridSize.x);
120             theBGrid[b][r].resize(gridSize.x);
121             theCGrid[b][r].resize(gridSize.x);
122          }
123 
124       }
125       theGridSize = gridSize;
126    }
127 
128 }
129 
130 
setBaseToAverage()131 void ossimAtCorrGridRemapper::setBaseToAverage()
132 {
133    ossim_uint32 idxBand;
134    vector<double> xaAverage(theAGrid.size());
135    vector<double> xcAverage(theBGrid.size());
136    vector<double> xbAverage(theCGrid.size());
137    // double aAverage=0.0, bAverage=0.0, cAverag=0.0;
138 
139 
140    if((theAGrid.size() != theBGrid.size())||
141       (theAGrid.size() != theCGrid.size())||
142       (theAGrid.size() == 0))
143    {
144       return;
145    }
146 
147    for(idxBand = 0; idxBand < theAGrid.size(); ++idxBand)
148    {
149       ossim_uint32 idxRow = 0;
150       xaAverage[idxBand] = 0.0;
151       xbAverage[idxBand] = 0.0;
152       xcAverage[idxBand] = 0.0;
153       for(idxRow = 0; idxRow < theAGrid[idxBand].size();++idxRow)
154       {
155          ossim_uint32 idxCol = 0;
156          for(idxCol = 0; idxCol < theAGrid[idxBand][idxRow].size();++idxCol)
157          {
158             xaAverage[idxBand] += theAGrid[idxBand][idxRow][idxCol];
159 
160          }
161       }
162       for(idxRow = 0; idxRow < theBGrid[idxBand].size();++idxRow)
163       {
164          ossim_uint32 idxCol = 0;
165          for(idxCol = 0; idxCol < theBGrid[idxBand][idxRow].size();++idxCol)
166          {
167             xbAverage[idxBand] += theBGrid[idxBand][idxRow][idxCol];
168          }
169       }
170       for(idxRow = 0; idxRow < theCGrid[idxBand].size();++idxRow)
171       {
172          ossim_uint32 idxCol = 0;
173          for(idxCol = 0; idxCol < theCGrid[idxBand][idxRow].size();++idxCol)
174          {
175             xaAverage[idxBand] += theCGrid[idxBand][idxRow][idxCol];
176             xbAverage[idxBand] += theCGrid[idxBand][idxRow][idxCol];
177             xcAverage[idxBand] += theCGrid[idxBand][idxRow][idxCol];
178 
179          }
180       }
181    }
182 
183    for(idxBand = 0; idxBand < theAGrid.size(); ++idxBand)
184    {
185       xaAverage[idxBand] /=(double)(theGridSize.x*theGridSize.y);
186       xbAverage[idxBand] /=(double)(theGridSize.x*theGridSize.y);
187       xcAverage[idxBand] /=(double)(theGridSize.x*theGridSize.y);
188    }
189 
190    theXaArray = xaAverage;
191    theXbArray = xbAverage;
192    theXcArray = xcAverage;
193 }
194 
195 /*!
196  * Method to the load (recreate) the state of an object from a keyword
197  * list.  Return true if ok or false on error.
198  */
loadState(const ossimKeywordlist & kwl,const char * prefix)199 bool ossimAtCorrGridRemapper::loadState(const ossimKeywordlist& kwl,
200                                         const char* prefix)
201 {
202    const char* MODULE = "ossimAtCorrGridRemapper::loadState";
203    theAGrid.clear();
204    theBGrid.clear();
205    theCGrid.clear();
206 
207    if (!theTile || !theSurfaceReflectance)
208    {
209       cerr << MODULE << " ERROR:"
210            << "Not initialized..." << endl;
211       return false;
212    }
213    theUseInterpolationFlag=true;
214    ossim_uint32 bands = theTile->getNumberOfBands();
215 
216    theAGrid.resize(bands);
217    theBGrid.resize(bands);
218    theCGrid.resize(bands);
219 
220 
221    const char* rowsLookup = NULL;
222    const char* colsLookup = NULL;
223    for(ossim_uint32 band = 0; band < bands; ++band)
224    {
225       ossim_uint32 r = 0;
226       ossim_uint32 c = 0;
227       ossimString gridString = "band";
228       gridString += ossimString::toString(band+1);
229       gridString += ".grid";
230 
231       rowsLookup = kwl.find(prefix,
232                             gridString + ".rows");
233 
234       colsLookup = kwl.find(prefix,
235                             gridString + ".cols");
236       if(rowsLookup&&colsLookup)
237       {
238          cout << "both keywords needed: " << (gridString+".rows") << endl
239               << (gridString+".cols") << endl;
240 
241          theUseInterpolationFlag=false;
242          return false;
243       }
244 
245       ossim_uint32 rows = ossimString(rowsLookup).toULong();
246       ossim_uint32 cols = ossimString(colsLookup).toULong();
247 
248       if(cols&&rows)
249       {
250          cout << "value for cols and rows keyword have 0" << endl;
251          theUseInterpolationFlag=false;
252          return false;
253       }
254 
255       theAGrid[band].resize(rows);
256       theBGrid[band].resize(rows);
257       theCGrid[band].resize(rows);
258       for(r = 0; r < rows; ++r)
259       {
260          theAGrid[band][r].resize(cols);
261          theBGrid[band][r].resize(cols);
262          theCGrid[band][r].resize(cols);
263       }
264 
265       ossim_uint32 idx = 1;
266       const char* aLookup;
267       const char* bLookup;
268       const char* cLookup;
269       for(r = 0; r < rows; ++r)
270       {
271          for(c = 0; c < cols; ++c)
272          {
273             aLookup = kwl.find(prefix, gridString+".a"+ossimString::toString(idx));
274             bLookup = kwl.find(prefix, gridString+".b"+ossimString::toString(idx));
275             cLookup = kwl.find(prefix, gridString+".c"+ossimString::toString(idx));
276             theAGrid[band][r][c] = ossimString(aLookup).toDouble();
277             theBGrid[band][r][c] = ossimString(bLookup).toDouble();
278             theCGrid[band][r][c] = ossimString(cLookup).toDouble();
279 
280             ++idx;
281          }
282       }
283 
284       theGridSize.x = cols;
285       theGridSize.y = rows;
286       setBaseToAverage();
287    }
288 
289    return true;
290 }
291 
saveState(ossimKeywordlist & kwl,const char * prefix) const292 bool ossimAtCorrGridRemapper::saveState(ossimKeywordlist& kwl,
293                                         const char* prefix)const
294 {
295 
296    ossim_uint32 bands = (ossim_uint32)theAGrid.size();
297 
298    for(ossim_uint32 band = 0; band < bands; ++band)
299    {
300       int idx = 1;
301       int r = 0;
302       int c = 0;
303       ossimString gridString = "band";
304       gridString += ossimString::toString(band+1);
305       gridString += ".grid";
306 
307       ossim_uint32 rows = (ossim_uint32)theAGrid[band].size();
308       kwl.add(prefix,
309               gridString+".rows",
310               rows,
311               true);
312       ossim_uint32 cols = (ossim_uint32)theAGrid[band][0].size();
313       kwl.add(prefix,
314               gridString+".cols",
315               cols,
316               true);
317       for(r = 0; r < theGridSize.y; ++r)
318       {
319          for(c = 0; c < theGridSize.x; ++c)
320          {
321             kwl.add(prefix,
322                     gridString+".a"+ossimString::toString(idx),
323                     theAGrid[band][r][c],
324                     true);
325             kwl.add(prefix,
326                     gridString+".b"+ossimString::toString(idx),
327                     theAGrid[band][r][c],
328                     true);
329             kwl.add(prefix,
330                     gridString+".c"+ossimString::toString(idx),
331                     theAGrid[band][r][c],
332                     true);
333 
334             ++idx;
335          }
336       }
337    }
338 
339    return ossimAtCorrRemapper::saveState(kwl, prefix);
340 }
341