OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimRpcSolver.cpp
Go to the documentation of this file.
1 //**************************************************************************************************
2 //
3 // OSSIM Open Source Geospatial Data Processing Library
4 // See top level LICENSE.txt file for license information
5 //
6 //**************************************************************************************************
7 
14 
15 using namespace ossim;
16 using namespace std;
17 
18 static const ossim_uint32 STARTING_GRID_SIZE = 8;
19 static const ossim_uint32 ENDING_GRID_SIZE = 64;
20 
21 ossimRpcSolver::ossimRpcSolver(bool useElevation, bool useHeightAboveMSLFlag)
22 : theUseElevationFlag(useElevation),
23  theHeightAboveMSLFlag(useHeightAboveMSLFlag),
24  theMeanResidual(0),
25  theMaxResidual(0)
26 {
27 }
28 
30  ossimProjection* proj,
31  ossim_uint32 xSamples,
32  ossim_uint32 ySamples)
33 {
35  geom->setProjection(proj);
36  solveCoefficients(imageBounds, geom.get(), xSamples, ySamples);
37 }
38 
40  ossimImageGeometry* geom,
41  ossim_uint32 xSamples,
42  ossim_uint32 ySamples)
43 {
44  if (!geom || !(geom->getProjection()))
45  return;
46  theRefGeom = geom;
47 
48  std::vector<ossimGpt> groundPoints;
49  std::vector<ossimDpt> imagePoints;
51  ossimGpt gpt;
52  ossimGpt defaultGround;
53  if (ySamples <= 1)
54  ySamples = STARTING_GRID_SIZE;
55  if (xSamples <= 1)
56  xSamples = STARTING_GRID_SIZE;
57  srand(time(0));
58  double Dx = imageBounds.width()/(xSamples-1);
59  double Dy = imageBounds.height()/(ySamples-1);
60  ossimDpt dpt;
61  for(y = 0; y < ySamples; ++y)
62  {
63  dpt.y = y*Dy + imageBounds.ul().y;
64  for(x = 0; x < xSamples; ++x)
65  {
66  dpt.x = x*Dx + imageBounds.ul().x;
68  geom->localToWorld(dpt, gpt);
69  else
70  geom->localToWorld(dpt, 0, gpt);
71 
72  if (gpt.isLatLonNan())
73  continue;
74 
75  if(gpt.isHgtNan())
76  gpt.height(0.0);
77 
78  gpt.changeDatum(defaultGround.datum());
80  {
82  if(ossim::isnan(h) == false)
83  gpt.height(h);
84  }
85 
86  imagePoints.push_back(dpt);
87  groundPoints.push_back(gpt);
88  }
89  }
90  solveCoefficients(imagePoints, groundPoints);
91 }
92 
93 void ossimRpcSolver::solveCoefficients(const std::vector<ossimDpt>& imagePoints,
94  const std::vector<ossimGpt>& groundControlPoints)
95 {
96  if((imagePoints.size() != groundControlPoints.size()))
97  return;
98 
99  // we will first create f which holds the result of f(x,y,z).
100  // This basically holds the cooresponding image point for each
101  // ground control point. One for x and a second array for y
102  int numPoints = imagePoints.size();
103  std::vector<double> fx, fy;
104 
105  // Holds the x, y, z vectors
106  //
107  std::vector<double> x;
108  std::vector<double> y;
109  std::vector<double> z;
110  ossim_uint32 c = 0;
111  fx.resize(imagePoints.size());
112  fy.resize(imagePoints.size());
113  x.resize(imagePoints.size());
114  y.resize(imagePoints.size());
115  z.resize(imagePoints.size());
116 
117  // compute the image bounds for the given image points
118  ossimDrect rect(imagePoints);
119  ossimDpt centerImagePoint = rect.midPoint();
120 
121  // get the width and height that will be used in data normalization
122  ossim_float64 w = rect.width();
123  ossim_float64 h = rect.height();
124 
125  double latSum=0.0;
126  double lonSum=0.0;
127  double heightSum=0.0;
128 
129  // find the center ground Use elevation only if its enabled
130  for(c = 0; c < groundControlPoints.size();++c)
131  {
132  if(ossim::isnan(groundControlPoints[c].latd()) == false)
133  {
134  latSum += groundControlPoints[c].latd();
135  }
136  if(ossim::isnan(groundControlPoints[c].lond()) == false)
137  {
138  lonSum += groundControlPoints[c].lond();
139  }
140  if(!groundControlPoints[c].isHgtNan())
141  {
143  {
144  heightSum += groundControlPoints[c].height();
145  }
146  }
147  }
148 
149  // set the center ground for the offset
150  //
151  ossimGpt centerGround(latSum/groundControlPoints.size(),
152  lonSum/groundControlPoints.size(),
153  heightSum/groundControlPoints.size());
154 
155  // set up ground scales and deltas for normalization
156  ossim_float64 deltaLat = 0.0;
157  ossim_float64 deltaLon = 0.0;
158  ossim_float64 deltaHeight = 0.0;
159  ossim_float64 maxDeltaLat = 0.0;
160  ossim_float64 maxDeltaLon = 0.0;
161  ossim_float64 maxDeltaHeight = 0.0;
162  ossim_float64 heightTest = 0.0;
163  for(c = 0; c < groundControlPoints.size(); ++c)
164  {
165  deltaLat = (groundControlPoints[c].latd()-centerGround.latd());
166  deltaLon = (groundControlPoints[c].lond()-centerGround.lond());
167  if(!groundControlPoints[c].isHgtNan())
168  {
170  {
171  deltaHeight = groundControlPoints[c].height() - centerGround.height();
172  heightTest = groundControlPoints[c].height();
173  }
174  else
175  {
176  deltaHeight = 0.0;
177  heightTest = 0.0;
178  }
179  }
180  else
181  {
182  deltaHeight = 0.0;
183  }
184  fx[c] = (imagePoints[c].x - centerImagePoint.x)/(w/2.0);
185  fy[c] = (imagePoints[c].y - centerImagePoint.y)/(h/2.0);
186 
187  x[c] = deltaLon;
188  y[c] = deltaLat;
189  z[c] = deltaHeight;
190 
191  if(fabs(deltaLat) > maxDeltaLat)
192  maxDeltaLat = fabs(deltaLat);
193  if(fabs(deltaLon) > maxDeltaLon)
194  maxDeltaLon = fabs(deltaLon);
195  if(fabs(heightTest) > maxDeltaHeight)
196  maxDeltaHeight = fabs(heightTest);
197  }
198 
199  bool elevationEnabled = theUseElevationFlag;
200 
201  // if max delta is less than a degree set it to 1 degree.
202 // if(maxDeltaLat < 1.0)
203 // maxDeltaLat = 1.0;
204 // if(maxDeltaLon < 1.0)
205 // maxDeltaLon = 1.0;
206 
207  if(maxDeltaHeight < FLT_EPSILON)
208  elevationEnabled = false;
209  if(maxDeltaHeight < 1.0)
210  maxDeltaHeight = 1.0;
211 
212  // set the height scale to something pretty large
213  if(!elevationEnabled)
214  {
215  maxDeltaHeight = 1.0/DBL_EPSILON;
216  maxDeltaHeight = 10000;
217  centerGround.height(0.0);
218  }
219  // normalize the ground points
220  for(c = 0; c < groundControlPoints.size(); ++c)
221  {
222  x[c] /= maxDeltaLon;
223  y[c] /= maxDeltaLat;
224  z[c] /= maxDeltaHeight;
225  }
226 
229  theRpcModel->theLineOffset = centerImagePoint.y;
230  theRpcModel->theSampOffset = centerImagePoint.x;
231  theRpcModel->theLineScale = h/2.0;
232  theRpcModel->theSampScale = w/2.0;
233 
234  theRpcModel->theLatScale = maxDeltaLat;
235  theRpcModel->theLonScale = maxDeltaLon;
236  theRpcModel->theHgtScale = maxDeltaHeight;
237 
238  theRpcModel->theLatOffset = centerGround.lat;
239  theRpcModel->theLonOffset = centerGround.lon;
240  theRpcModel->theHgtOffset = centerGround.hgt;
241 
243  theRpcModel->theHgtOffset = 0.0;
244 
245  NEWMAT::ColumnVector coeffxVec;
246  NEWMAT::ColumnVector coeffyVec;
247 
248  // perform a least squares fit for sample values found in f
249  // given the world values with variables x, y, z
250  solveCoefficients(coeffxVec, fx, x, y, z);
251 
252  // perform a least squares fit for line values found in f
253  // given the world values with variables x, y, z
254  solveCoefficients(coeffyVec, fy, x, y, z);
255 
256  // there are 20 numerator coefficients and 19 denominator coefficients.
257  // I believe that the very first one for the denominator coefficients is fixed at 1.
258  theRpcModel->theLineNumCoef[0] = coeffyVec[0];
259  theRpcModel->theLineDenCoef[0] = 1.0;
260  theRpcModel->theSampNumCoef[0] = coeffxVec[0];
261  theRpcModel->theSampDenCoef[0] = 1.0;
262  for (int i=1; i<20; i++)
263  {
264  theRpcModel->theLineNumCoef[i] = coeffyVec[i];
265  theRpcModel->theLineDenCoef[i] = coeffyVec[i+19];
266  theRpcModel->theSampNumCoef[i] = coeffxVec[i];
267  theRpcModel->theSampDenCoef[i] = coeffxVec[i+19];
268  }
269 
270  // now lets compute the RMSE for the given control points by feeding it
271  // back through the modeled RPC
272  ossim_float64 sumSquareError = 0.0;
273  ossim_uint32 idx = 0;
274 
275  theMaxResidual = 0;
276  for (idx = 0; idx<imagePoints.size(); idx++)
277  {
278  ossimDpt evalPt;
279  evalPoint(groundControlPoints[idx], evalPt);
280  ossim_float64 len = (evalPt - imagePoints[idx]).length();
281  if (len > theMaxResidual)
282  theMaxResidual = len;
283  sumSquareError += (len*len);
284  }
285 
286  // set the error
287  theMeanResidual = sqrt(sumSquareError/imagePoints.size());
288 }
289 
290 bool ossimRpcSolver::solve(const ossimDrect& imageBounds,
291  ossimImageGeometry* geom,
292  const double& tolerance)
293 {
294  static const char* MODULE = "ossimRpcSolver::solve() ";
295 
296  if (!geom)
297  return false;
298 
299  theRefGeom = geom;
300  ossimDpt ul = imageBounds.ul();
301  ossim_float64 w = imageBounds.width();
302  ossim_float64 h = imageBounds.height();
303  ossimDpt ipt, irpc;
304  ossimGpt gpt;
305 
306  // Start at the minimum grid size:
307  ossim_uint32 xSamples = STARTING_GRID_SIZE;
308  ossim_uint32 ySamples = STARTING_GRID_SIZE;
309 
310  // Loop until error is below threshold:
311  bool converged = false;
312  while (!converged)
313  {
314  double residual = 0;
315  double sumResiduals = 0;
316  int numResiduals = 0;
317  theMaxResidual = 0;
318 
319  converged = true; // hope for the best and get proved otherwise below
320  solveCoefficients(imageBounds, geom, xSamples, ySamples);
321 
322  // Sample along x and y directions to accumulate errors:
323  double deltaX = w/(xSamples-1);
324  double deltaY = h/(ySamples-1);
325 
326  // Sample the midpoints between image grid used to compute RPC:
327  for (ossim_uint32 y=0; y<ySamples-1; ++y)
328  {
329  ipt.y = deltaY*((double)y + 0.5) + ul.y;
330  for (ossim_uint32 x=0; x<xSamples-1; ++x)
331  {
332  // Forward projection using input model:
333  ipt.x = deltaX*((double)x + 0.5) + ul.x;
335  geom->localToWorld(ipt, gpt);
336  else
337  geom->localToWorld(ipt, 0, gpt);
339  {
341  if(ossim::isnan(h) == false)
342  gpt.height(h);
343  }
344 
345  // Reverse projection using RPC:
346  evalPoint(gpt, irpc);
347 
348  // Compute residual and accumulate:
349  residual = (ipt-irpc).length();
350  if (residual > theMaxResidual)
351  theMaxResidual = residual;
352  sumResiduals += residual;
353  ++numResiduals;
354  }
355  }
356 
357  theMeanResidual = sumResiduals/numResiduals;
358  if (theMaxResidual > tolerance)
359  converged = false;
360 
361 #if 1
362  { //### DEBUG BLOCK ###
364  <<"\n sampling grid size: ("<<xSamples<<", "<<ySamples<<")"
365  <<"\n mean residual: "<<theMeanResidual
366  <<"\n max residual: "<<theMaxResidual
367  <<"\n converged: "<<ossimString::toString(converged)<<endl;
368  }
369 #endif
370 
371  if ((xSamples >= ENDING_GRID_SIZE) && (ySamples >= ENDING_GRID_SIZE))
372  break;
373 
374  if (!converged)
375  {
376  xSamples *= 2;
377  if (xSamples > ENDING_GRID_SIZE)
378  xSamples = ENDING_GRID_SIZE;
379  ySamples *= 2;
380  if (ySamples > ENDING_GRID_SIZE)
381  ySamples = ENDING_GRID_SIZE;
382  }
383  }
384 
385  // Was testing the max residual. But use the mean for final test:
386  if (theMeanResidual <= tolerance)
387  converged = true;
388 
389  if (!converged)
390  {
392  << "WARNING: Unable to converge on desired error tolerance ("<<tolerance<<" p).\n"
393  <<" RMS residual error: " << theMeanResidual << "\n"
394  <<" Max residual error: " << theMaxResidual<<std::endl;
395  }
396  else if (theMaxResidual > tolerance)
397  {
399  << "WARNING: While the RPC solution did converge, at least one residual ("
400  <<theMaxResidual<<") is larger than the desired error tolerance ("<<tolerance<<" p)."
401  << std::endl;
402  }
403  return converged;
404 }
405 
406 bool ossimRpcSolver::solve(const ossimFilename& imageFilename,
407  const double& pixel_tolerance)
408 {
409  // Establish input geometry:
411  if(!h.valid())
412  return false;
413 
415  ossimDrect imageRect (h->getBoundingRect());
416 
417  return solve(imageRect, geom.get(), pixel_tolerance);
418 }
419 
420 
422 {
423  return theMeanResidual;
424 }
425 
427 {
428  return theMaxResidual;
429 }
430 
431 void ossimRpcSolver::solveInitialCoefficients(NEWMAT::ColumnVector& coeff,
432  const std::vector<double>& f,
433  const std::vector<double>& x,
434  const std::vector<double>& y,
435  const std::vector<double>& z)const
436 {
437  ossim_uint32 idx = 0;
438  NEWMAT::Matrix m;
439  NEWMAT::ColumnVector r((int)f.size());
440  for(idx = 0; idx < f.size(); ++idx)
441  {
442  r[idx] = f[idx];
443  }
444  setupSystemOfEquations(m, r, x, y, z);
445 
446  coeff = invert(m.t()*m)*m.t()*r;
447 }
448 
449 void ossimRpcSolver::solveCoefficients(NEWMAT::ColumnVector& coeff,
450  const std::vector<double>& f,
451  const std::vector<double>& x,
452  const std::vector<double>& y,
453  const std::vector<double>& z)const
454 {
455  // this is an iterative linear least square fit. We really pobably need
456  // a nonlinear fit instead
457  //
458  ossim_uint32 idx = 0;
459  NEWMAT::Matrix m;
460 
461  NEWMAT::ColumnVector r((int)f.size());
462 
463  for(idx = 0; idx < f.size(); ++idx)
464  {
465  r[idx] = f[idx];
466  }
467 
468  NEWMAT::ColumnVector tempCoeff;
469  NEWMAT::DiagonalMatrix weights((int)f.size());
470  NEWMAT::ColumnVector denominator(20);
471 
472  // initialize the weight matrix to the identity
473  //
474  for(idx = 0; idx < f.size(); ++idx)
475  {
476  weights[idx] = 1.0;
477  }
478 
479  double residualValue = 1.0/FLT_EPSILON;
480  ossim_uint32 iterations = 0;
481  NEWMAT::Matrix w2;
482  do
483  {
484  w2 = weights*weights;
485 
486 #if 0
487  { //### DEBUG ###
488  cout<<"\nw2 = \n"<<w2<<endl;
489  cout<<"\nr = "<<r<<endl;
490  }
491 #endif
492 
493  // sets up the matrix to hold the system of equations
494  setupSystemOfEquations(m, r, x, y, z);
495 
496  // solve the least squares solution. Note: the invert is used
497  // to do a Singular Value Decomposition for the inverse since the
498  // matrix is more than likely singular. Slower but more robust
499 #if 0
500  { //### DEBUG ###
501  NEWMAT::Matrix mt = m.t();
502  cout<<"\nm = "<<m<<endl;
503  cout<<"\nmt = "<<mt<<endl;
504 
505  NEWMAT::Matrix mtw2 = m.t()*w2;
506  cout<<"\nmtw2 = "<<mtw2<<endl;
507  NEWMAT::Matrix mtw2m = mtw2*m;
508  cout<<"\nmtw2m = "<<mtw2m<<endl;
509  NEWMAT::Matrix mtw2r = mtw2*r;
510  cout<<"\nmtw2r = "<<mtw2r<<endl;
511 
512  NEWMAT::Matrix mtw2m_inv = invert(mtw2m);
513  cout<<"\nmtw2m_inv = "<<mtw2m_inv<<endl;
514  tempCoeff = mtw2m_inv * mtw2r;
515  cout<<"\ntempCoeff = "<<tempCoeff<<endl;
516  }
517 #else
518  tempCoeff = invert(m.t()*w2*m)*m.t()*w2*r;
519 #endif
520 
521  // set up the weight matrix by using the denominator
522  for(idx = 0; idx < 19; ++idx)
523  {
524  denominator[idx+1] = tempCoeff[20+idx];
525  }
526  denominator[0] = 1.0;
527 
528  setupWeightMatrix(weights, denominator, r, x, y, z);
529 
530  // compute the residual
531  NEWMAT::ColumnVector residual = m.t()*w2*(m*tempCoeff-r);
532 
533  // now get the innerproduct
534  NEWMAT::Matrix tempRes = (residual.t()*residual);
535  residualValue = sqrt(tempRes[0][0]);
536 
537  ++iterations;
538 
539  } while ((residualValue > FLT_EPSILON) && (iterations < 10));
540  coeff = tempCoeff;
541 
542 }
543 
544 NEWMAT::Matrix ossimRpcSolver::invert(const NEWMAT::Matrix& m)const
545 {
546  ossim_uint32 idx = 0;
547  NEWMAT::DiagonalMatrix d;
548  NEWMAT::Matrix u;
549  NEWMAT::Matrix v;
550 
551  // decompose m.t*m which is stored in Temp into the singular values and vectors.
552  //
553  NEWMAT::SVD(m, d, u, v, true, true);
554 
555  // invert the diagonal
556  // this is just doing the reciprical fo all diagonal components and store back int
557  // d. ths compute d inverse.
558  //
559  for(idx=0; idx < (ossim_uint32)d.Ncols(); ++idx)
560  {
561  if(d[idx] > FLT_EPSILON)
562  {
563  d[idx] = 1.0/d[idx];
564  }
565  else
566  {
567  d[idx] = 0.0;
568  }
569  }
570 
571  //compute inverse of decomposed m;
572  return v*d*u.t();
573 }
574 
575 
576 void ossimRpcSolver::setupSystemOfEquations(NEWMAT::Matrix& equations,
577  const NEWMAT::ColumnVector& f,
578  const std::vector<double>& x,
579  const std::vector<double>& y,
580  const std::vector<double>& z)const
581 {
582  ossim_uint32 idx;
583  equations.ReSize(f.Nrows(), 39);
584 
585  for(idx = 0; idx < (ossim_uint32)f.Nrows();++idx)
586  {
587  equations[idx][0] = 1;
588  equations[idx][1] = x[idx];
589  equations[idx][2] = y[idx];
590  equations[idx][3] = z[idx];
591  equations[idx][4] = x[idx]*y[idx];
592  equations[idx][5] = x[idx]*z[idx];
593  equations[idx][6] = y[idx]*z[idx];
594  equations[idx][7] = x[idx]*x[idx];
595  equations[idx][8] = y[idx]*y[idx];
596  equations[idx][9] = z[idx]*z[idx];
597  equations[idx][10] = x[idx]*y[idx]*z[idx];
598  equations[idx][11] = x[idx]*x[idx]*x[idx];
599  equations[idx][12] = x[idx]*y[idx]*y[idx];
600  equations[idx][13] = x[idx]*z[idx]*z[idx];
601  equations[idx][14] = x[idx]*x[idx]*y[idx];
602  equations[idx][15] = y[idx]*y[idx]*y[idx];
603  equations[idx][16] = y[idx]*z[idx]*z[idx];
604  equations[idx][17] = x[idx]*x[idx]*z[idx];
605  equations[idx][18] = y[idx]*y[idx]*z[idx];
606  equations[idx][19] = z[idx]*z[idx]*z[idx];
607  equations[idx][20] = -f[idx]*x[idx];
608  equations[idx][21] = -f[idx]*y[idx];
609  equations[idx][22] = -f[idx]*z[idx];
610  equations[idx][23] = -f[idx]*x[idx]*y[idx];
611  equations[idx][24] = -f[idx]*x[idx]*z[idx];
612  equations[idx][25] = -f[idx]*y[idx]*z[idx];
613  equations[idx][26] = -f[idx]*x[idx]*x[idx];
614  equations[idx][27] = -f[idx]*y[idx]*y[idx];
615  equations[idx][28] = -f[idx]*z[idx]*z[idx];
616  equations[idx][29] = -f[idx]*x[idx]*y[idx]*z[idx];
617  equations[idx][30] = -f[idx]*x[idx]*x[idx]*x[idx];
618  equations[idx][31] = -f[idx]*x[idx]*y[idx]*y[idx];
619  equations[idx][32] = -f[idx]*x[idx]*z[idx]*z[idx];
620  equations[idx][33] = -f[idx]*x[idx]*x[idx]*y[idx];
621  equations[idx][34] = -f[idx]*y[idx]*y[idx]*y[idx];
622  equations[idx][35] = -f[idx]*y[idx]*z[idx]*z[idx];
623  equations[idx][36] = -f[idx]*x[idx]*x[idx]*z[idx];
624  equations[idx][37] = -f[idx]*y[idx]*y[idx]*z[idx];
625  equations[idx][38] = -f[idx]*z[idx]*z[idx]*z[idx];
626  }
627 }
628 
629 void ossimRpcSolver::setupWeightMatrix(NEWMAT::DiagonalMatrix& result, // holds the resulting weights
630  const NEWMAT::ColumnVector& coefficients,
631  const NEWMAT::ColumnVector& f,
632  const std::vector<double>& x,
633  const std::vector<double>& y,
634  const std::vector<double>& z)const
635 {
636  result.ReSize(f.Nrows());
637  ossim_uint32 idx = 0;
638  ossim_uint32 idx2 = 0;
639  NEWMAT::RowVector row(coefficients.Nrows());
640 
641  for(idx = 0; idx < (ossim_uint32)f.Nrows(); ++idx)
642  {
643  row[0] = 1;
644  row[1] = x[idx];
645  row[2] = y[idx];
646  row[3] = z[idx];
647  row[4] = x[idx]*y[idx];
648  row[5] = x[idx]*z[idx];
649  row[6] = y[idx]*z[idx];
650  row[7] = x[idx]*x[idx];
651  row[8] = y[idx]*y[idx];
652  row[9] = z[idx]*z[idx];
653  row[10] = x[idx]*y[idx]*z[idx];
654  row[11] = x[idx]*x[idx]*x[idx];
655  row[12] = x[idx]*y[idx]*y[idx];
656  row[13] = x[idx]*z[idx]*z[idx];
657  row[14] = x[idx]*x[idx]*y[idx];
658  row[15] = y[idx]*y[idx]*y[idx];
659  row[16] = y[idx]*z[idx]*z[idx];
660  row[17] = x[idx]*x[idx]*z[idx];
661  row[18] = y[idx]*y[idx]*z[idx];
662  row[19] = z[idx]*z[idx]*z[idx];
663 
664  result[idx] = 0.0;
665  for(idx2 = 0; idx2 < (ossim_uint32)row.Ncols(); ++idx2)
666  {
667  result[idx] += row[idx2]*coefficients[idx2];
668  }
669 
670  if(result[idx] > FLT_EPSILON)
671  {
672  result[idx] = 1.0/result[idx];
673  }
674  }
675 }
676 
677 void ossimRpcSolver::evalPoint(const ossimGpt& gpt, ossimDpt& ipt) const
678 {
679  if (!theRpcModel)
680  {
681  ipt.makeNan();
682  return;
683  }
684 
685  theRpcModel->worldToLineSample(gpt, ipt);
686 }
687 
688 
690 {
691  ossimNitfRpcBTag* rpcbTag = new ossimNitfRpcBTag();
692  rpcbTag->setRpcModelParams(theRpcModel);
693 
694  // Return it as an ossimRefPtr<ossimNitfRegisteredTag>...
696 
697  return tag;
698 }
double theSampOffset
PolynomialType thePolyType
virtual void worldToLineSample(const ossimGpt &world_point, ossimDpt &image_point) const
worldToLineSample() Overrides base class implementation.
double theSampNumCoef[20]
ossim_uint32 x
void setProjection(ossimProjection *projection)
Sets the projection to be used for local-to-world coordinate transformation.
ossim_float64 width() const
Definition: ossimDrect.h:522
virtual ossimImageHandler * open(const ossimFilename &fileName, bool trySuffixFirst=true, bool openOverview=true) const
open that takes a filename.
ossimRefPtr< ossimNitfRegisteredTag > getNitfRpcBTag() const
ossim_uint32 y
bool valid() const
Definition: ossimRefPtr.h:75
This code was derived from https://gist.github.com/mshockwave.
Definition: Barrier.h:8
const ossimDpt & ul() const
Definition: ossimDrect.h:339
double y
Definition: ossimDpt.h:165
void setupSystemOfEquations(NEWMAT::Matrix &equations, const NEWMAT::ColumnVector &f, const std::vector< double > &x, const std::vector< double > &y, const std::vector< double > &z) const
static ossimString toString(bool aValue)
Numeric to string methods.
virtual void setRpcModelParams(ossimRefPtr< ossimRpcModel > rpc)
For generating the RPC tag from existing RPC Model.
The layout of RPC00B is the same as RPC00A.
static ossimElevManager * instance()
METHOD: instance() Implements singelton pattern.
double theLonScale
void solveCoefficients(const ossimDrect &imageBounds, ossimProjection *imageProj, ossim_uint32 xSamples=8, ossim_uint32 ySamples=8)
This will convert any projector to an RPC model.
ossimRpcSolver(bool useElevation=false, bool useHeightAboveMSLFlag=false)
The use elvation flag will deterimne if we force the height t be 0.
double theLineScale
void changeDatum(const ossimDatum *datum)
This will actually perform a shift.
Definition: ossimGpt.cpp:316
bool isHgtNan() const
Definition: ossimGpt.h:143
const ossimDatum * datum() const
datum().
Definition: ossimGpt.h:196
double theSampDenCoef[20]
void evalPoint(const ossimGpt &gpt, ossimDpt &ipt) const
double theLineNumCoef[20]
double theLatOffset
double ossim_float64
bool solve(const ossimDrect &aoiBounds, ossimImageGeometry *geom, const double &pixel_tolerance=0.5)
Similar to the other solve methods except that the final grid size is established iteratively so that...
ossim_float64 theMaxResidual
double theHgtOffset
double theLonOffset
void setupWeightMatrix(NEWMAT::DiagonalMatrix &result, const NEWMAT::ColumnVector &coefficients, const NEWMAT::ColumnVector &f, const std::vector< double > &x, const std::vector< double > &y, const std::vector< double > &z) const
virtual ossimRefPtr< ossimImageGeometry > getImageGeometry()
Returns the image geometry object associated with this tile source or NULL if non defined...
bool localToWorld(const ossimDpt &local_pt, ossimGpt &world_pt) const
Exposes the 3D projection from image to world coordinates.
double theLatScale
#define FLT_EPSILON
unsigned int ossim_uint32
double height() const
Definition: ossimGpt.h:107
void SVD(const Matrix &, DiagonalMatrix &, Matrix &, Matrix &, bool=true, bool=true)
Definition: svd.cpp:26
ossimRefPtr< ossimRpcModel > theRpcModel
#define DBL_EPSILON
ossim_float64 height() const
Definition: ossimDrect.h:517
double getRmsError() const
Container class that holds both 2D transform and 3D projection information for an image Only one inst...
ossim_float64 theMeanResidual
double getMaxError() const
const ossimProjection * getProjection() const
Access methods for projection (may be NULL pointer).
virtual void solveInitialCoefficients(NEWMAT::ColumnVector &coeff, const std::vector< double > &f, const std::vector< double > &x, const std::vector< double > &y, const std::vector< double > &z) const
bool theHeightAboveMSLFlag
virtual double getHeightAboveMSL(const ossimGpt &gpt)
Height access methods:
ossimDpt midPoint() const
Definition: ossimDrect.h:817
NEWMAT::Matrix invert(const NEWMAT::Matrix &m) const
Inverts using the SVD method.
double x
Definition: ossimDpt.h:164
double theSampScale
static ossimImageHandlerRegistry * instance()
virtual ossimIrect getBoundingRect(ossim_uint32 resLevel=0) const
Returns zero-based bounding rectangle of the image.
ossimRefPtr< ossimImageGeometry > theRefGeom
double theLineDenCoef[20]
bool isLatLonNan() const
Definition: ossimGpt.h:142
double theLineOffset
double theHgtScale
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
void makeNan()
Definition: ossimDpt.h:65
bool isnan(const float &v)
isnan Test for floating point Not A Number (NAN) value.
Definition: ossimCommon.h:91