OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimRpcProjection.cpp
Go to the documentation of this file.
1 //*****************************************************************************
2 // FILE: ossimRpcModel.cc
3 //
4 // Copyright (C) 2004 Intelligence Data Systems.
5 //
6 // LGPL
7 //
8 // AUTHOR: Garrett Potts
9 //
10 //*****************************************************************************
11 //$Id: ossimRpcProjection.cpp 17206 2010-04-25 23:20:40Z dburken $
12 
21 
24 
25 #include <ossim/base/ossimGpt.h>
26 #include <ossim/base/ossimDpt.h>
29 #include <cstdio>
30 #include <fstream>
31 #include <iostream>
32 #include <algorithm>
33 #include <ossim/matrix/newmatrc.h>
34 
35 //***
36 // Define Trace flags for use within this file:
37 //***
38 #include <ossim/base/ossimTrace.h>
39 static ossimTrace traceExec ("ossimRpcProjection:exec");
40 static ossimTrace traceDebug ("ossimRpcProjection:debug");
41 
42 //static const int MODEL_VERSION_NUMBER = 1;
43 static const int NUM_COEFFS = 20;
44 static const char* MODEL_TYPE = "ossimRpcModel";
45 static const char* POLY_TYPE_KW = "polynomial_format";
46 static const char* LINE_SCALE_KW = "line_scale";
47 static const char* SAMP_SCALE_KW = "samp_scale";
48 static const char* LAT_SCALE_KW = "lat_scale";
49 static const char* LON_SCALE_KW = "long_scale";
50 static const char* HGT_SCALE_KW = "height_scale";
51 static const char* LINE_OFFSET_KW = "line_off";
52 static const char* SAMP_OFFSET_KW = "samp_off";
53 static const char* LAT_OFFSET_KW = "lat_off";
54 static const char* LON_OFFSET_KW = "long_off";
55 static const char* HGT_OFFSET_KW = "height_off";
56 static const char* LINE_NUM_COEF_KW = "line_num_coeff_";
57 static const char* LINE_DEN_COEF_KW = "line_den_coeff_";
58 static const char* SAMP_NUM_COEF_KW = "samp_num_coeff_";
59 static const char* SAMP_DEN_COEF_KW = "samp_den_coeff_";
60 
61 static const ossim_int32 INTRACK_OFFSET = 0;
62 static const ossim_int32 CRTRACK_OFFSET = 1;
63 static const ossim_int32 INTRACK_SCALE = 2;
64 static const ossim_int32 CRTRACK_SCALE = 3;
65 static const ossim_int32 MAP_ROTATION = 4;
66 //static const ossim_int32 YAW_OFFSET;
67 static const ossim_int32 NUM_ADJUSTABLE_PARAMS = 5;
68 
69 static const ossimString PARAM_NAMES[] ={"intrack_offset",
70  "crtrack_offset",
71  "intrack_scale",
72  "crtrack_scale",
73  "map_rotation",
74  "yaw_offset"};
75 
76 static const ossimString PARAM_UNITS[] ={"pixel",
77  "pixel",
78  "scale",
79  "scale",
80  "degrees",
81  "degrees"};
82 
83 //*****************************************************************************
84 // DEFAULT CONSTRUCTOR: ossimRpcModel()
85 //
86 //*****************************************************************************
89  theIntrackOffset(0),
90  theCrtrackOffset(0),
91  theIntrackScale(0.0),
92  theCrtrackScale(0.0),
93  theYawSkew (0.0),
94  theCosMapRot (1.0),
95  theSinMapRot (0.0)
96 
97  {
98  if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimRpcProjection Default Constructor: entering..." << std::endl;
99 
101 
102  if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimRpcProjection Default Constructor: returning..." << std::endl;
103 }
104 
105 //*****************************************************************************
106 // COPY CONSTRUCTOR: ossimRpcProjection(ossimRpcProjection)
107 //
108 //*****************************************************************************
110  :
113  thePolyType (model.thePolyType),
114  theLineScale (model.theLineScale),
115  theSampScale (model.theSampScale),
116  theLatScale (model.theLatScale),
117  theLonScale (model.theLonScale),
118  theHgtScale (model.theHgtScale),
120  theSampOffset (model.theSampOffset),
121  theLatOffset (model.theLatOffset),
122  theLonOffset (model.theLonOffset),
123  theHgtOffset (model.theHgtOffset),
124  theIntrackOffset(model.theIntrackOffset),
125  theCrtrackOffset(model.theCrtrackOffset),
126  theIntrackScale(model.theIntrackScale),
127  theCrtrackScale(model.theCrtrackScale),
128  theYawSkew (model.theYawSkew),
129  theCosMapRot (model.theCosMapRot),
130  theSinMapRot (model.theSinMapRot)
131 {
132  if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimRpcProjection Copy Constructor: entering..." << std::endl;
133 
134  for (int i=0; i<20; i++)
135  {
136  theLineNumCoef[i] = model.theLineNumCoef[i];
137  theLineDenCoef[i] = model.theLineDenCoef[i];
138  theSampNumCoef[i] = model.theSampNumCoef[i];
139  theSampDenCoef[i] = model.theSampDenCoef[i];
140  }
141 
142  if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimRpcProjection Copy Constructor: returning..." << std::endl;
143 }
144 
145 //*****************************************************************************
146 // DESTRUCTOR: ~ossimRpcProjection()
147 //
148 //*****************************************************************************
150 {
151  if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ~ossimRpcProjection() Destructor: entering..." << std::endl;
152 
153  if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimNotify(ossimNotifyLevel_DEBUG): returning..." << std::endl;
154 }
155 
157 {
158  return this;
159 }
160 
162 {
163  return this;
164 }
165 
168 {
169  if (this != &source)
170  {
172 
173  thePolyType = source.thePolyType;
174  theLineScale = source.theLineScale;
175  theSampScale = source.theSampScale;
176  theLatScale = source.theLatScale;
177  theLonScale = source.theLonScale;
178  theHgtScale = source.theHgtScale;
179  theLineOffset = source.theLineOffset;
180  theSampOffset = source.theSampOffset;
181  theLatOffset = source.theLatOffset;
182  theLonOffset = source.theLonOffset;
183  theHgtOffset = source.theHgtOffset;
184  for (int i=0; i<20; i++)
185  {
186  theLineNumCoef[i] = source.theLineNumCoef[i];
187  theLineDenCoef[i] = source.theLineDenCoef[i];
188  theSampNumCoef[i] = source.theSampNumCoef[i];
189  theSampDenCoef[i] = source.theSampDenCoef[i];
190  }
191  }
192  return *this;
193 }
194 
196  ossim_float64 lineOffset,
197  ossim_float64 sampleScale,
198  ossim_float64 lineScale,
199  ossim_float64 latOffset,
200  ossim_float64 lonOffset,
201  ossim_float64 heightOffset,
202  ossim_float64 latScale,
203  ossim_float64 lonScale,
204  ossim_float64 heightScale,
205  const std::vector<double>& xNumeratorCoeffs,
206  const std::vector<double>& xDenominatorCoeffs,
207  const std::vector<double>& yNumeratorCoeffs,
208  const std::vector<double>& yDenominatorCoeffs,
209  PolynomialType polyType)
210 {
211  thePolyType = polyType;
212 
213  theLineScale = lineScale;
214  theSampScale = sampleScale;
215  theLatScale = latScale;
216  theLonScale = lonScale;
217  theHgtScale = heightScale;
218  theLineOffset = lineOffset;
219  theSampOffset = sampleOffset;
220  theLatOffset = latOffset;
221  theLonOffset = lonOffset;
222  theHgtOffset = heightOffset;
223 
224  if(xNumeratorCoeffs.size() == 20)
225  {
226  std::copy(xNumeratorCoeffs.begin(),
227  xNumeratorCoeffs.end(),
229  }
230  if(xDenominatorCoeffs.size() == 20)
231  {
232  std::copy(xDenominatorCoeffs.begin(),
233  xDenominatorCoeffs.end(),
235  }
236  if(yNumeratorCoeffs.size() == 20)
237  {
238  std::copy(yNumeratorCoeffs.begin(),
239  yNumeratorCoeffs.end(),
241  }
242  if(yDenominatorCoeffs.size() == 20)
243  {
244  std::copy(yDenominatorCoeffs.begin(),
245  yDenominatorCoeffs.end(),
247  }
248 }
249 
250 
251 //*****************************************************************************
252 // METHOD: ossimRpcProjection::worldToLineSample()
253 //
254 // Overrides base class implementation. Directly computes line-sample from
255 // the polynomials.
256 //*****************************************************************************
258  ossimDpt& imgPt) const
259 {
260  if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimRpcProjection::worldToLineSample(): entering..." << std::endl;
261 
262  if(ground_point.isLatNan() ||
263  ground_point.isLonNan() )
264  {
265  imgPt.makeNan();
266  return;
267  }
268 
269  //*
270  // Normalize the lat, lon, hgt:
271  //*
272  double nlat = (ground_point.lat - theLatOffset) / theLatScale;
273  double nlon = (ground_point.lon - theLonOffset) / theLonScale;
274  double nhgt;
275 
276  if(ossim::isnan(ground_point.hgt))
277  {
278  nhgt = (theHgtScale - theHgtOffset) / theHgtScale;
279  }
280  else
281  {
282  nhgt = (ground_point.hgt - theHgtOffset) / theHgtScale;
283  }
284 
285 
286  //***
287  // Compute the adjusted, normalized line (U) and sample (V):
288  //***
289  double Pu = polynomial(nlat, nlon, nhgt, theLineNumCoef);
290  double Qu = polynomial(nlat, nlon, nhgt, theLineDenCoef);
291  double Pv = polynomial(nlat, nlon, nhgt, theSampNumCoef);
292  double Qv = polynomial(nlat, nlon, nhgt, theSampDenCoef);
293  double U_rot = Pu / Qu;
294  double V_rot = Pv / Qv;
295 
296  //***
297  // U, V are normalized quantities. Need now to establish the image file
298  // line and sample. First, back out the adjustable parameter effects
299  // starting with rotation:
300  //***
301  double U = U_rot*theCosMapRot + V_rot*theSinMapRot;
302  double V = V_rot*theCosMapRot - U_rot*theSinMapRot;
303 
304  //***
305  // Now back out skew, scale, and offset adjustments:
306  //***
309 
310 
311  if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimRpcProjection::worldToLineSample(): returning..." << std::endl;
312 
313  return;
314 }
315 
317  ossimGpt& worldPoint) const
318 {
319  if(!imagePoint.hasNans())
320  {
321 
322  lineSampleHeightToWorld(imagePoint,
323  worldPoint.height(),
324  worldPoint);
325  }
326  else
327  {
328  worldPoint.makeNan();
329  }
330 }
331 
332 //*****************************************************************************
333 // METHOD: ossimRpcProjection::lineSampleHeightToWorld()
334 //
335 // Performs reverse projection of image line/sample to ground point.
336 // The imaging ray is intersected with a level plane at height = elev.
337 //
338 // NOTE: U = line, V = sample -- this differs from the convention.
339 //
340 //*****************************************************************************
342  const double& ellHeight,
343  ossimGpt& gpt) const
344 {
345  if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimRpcProjection::lineSampleHeightToWorld: entering..." << std::endl;
346 
347  //***
348  // Constants for convergence tests:
349  //***
350  static const int MAX_NUM_ITERATIONS = 10;
351  static const double CONVERGENCE_EPSILON = 0.1; // pixels
352 
353  //***
354  // The image point must be adjusted by the adjustable parameters as well
355  // as the scale and offsets given as part of the RPC param normalization.
356  //
357  // NOTE: U = line, V = sample
358  //***
359  double skew = (image_point.x-theSampOffset - theCrtrackOffset)*theYawSkew;
360  double U = (image_point.y-theLineOffset - theIntrackOffset+skew) / (theLineScale+theIntrackScale);
361  double V = (image_point.x-theSampOffset - theCrtrackOffset) / (theSampScale+theCrtrackScale);
362 
363  //***
364  // Rotate the normalized U, V by the map rotation error (adjustable param):
365  //***
366  double U_rot = theCosMapRot*U - theSinMapRot*V;
367  double V_rot = theSinMapRot*U + theCosMapRot*V;
368  U = U_rot; V = V_rot;
369 
370 
371  // now apply adjust intrack and cross track
372  //***
373  // Initialize quantities to be used in the iteration for ground point:
374  //***
375  double nlat = 0.0; // normalized latitude
376  double nlon = 0.0; // normalized longitude
377 
378  double nhgt;
379 
380  if(ossim::isnan(ellHeight))
381  {
382  nhgt = (theHgtScale - theHgtOffset) / theHgtScale; // norm height
383  }
384  else
385  {
386  nhgt = (ellHeight - theHgtOffset) / theHgtScale; // norm height
387  }
388 
389  double epsilonU = CONVERGENCE_EPSILON/(theLineScale+theIntrackScale);
390  double epsilonV = CONVERGENCE_EPSILON/(theSampScale+theCrtrackScale);
391  int iteration = 0;
392 
393  //***
394  // Declare variables only once outside the loop. These include:
395  // * polynomials (numerators Pu, Pv, and denominators Qu, Qv),
396  // * partial derivatives of polynomials wrt X, Y,
397  // * computed normalized image point: Uc, Vc,
398  // * residuals of normalized image point: deltaU, deltaV,
399  // * partial derivatives of Uc and Vc wrt X, Y,
400  // * corrections to normalized lat, lon: deltaLat, deltaLon.
401  //***
402  double Pu, Qu, Pv, Qv;
403  double dPu_dLat, dQu_dLat, dPv_dLat, dQv_dLat;
404  double dPu_dLon, dQu_dLon, dPv_dLon, dQv_dLon;
405  double Uc, Vc;
406  double deltaU, deltaV;
407  double dU_dLat, dU_dLon, dV_dLat, dV_dLon, W;
408  double deltaLat, deltaLon;
409 
410  //***
411  // Now iterate until the computed Uc, Vc is within epsilon of the desired
412  // image point U, V:
413  //***
414  do
415  {
416  //***
417  // Calculate the normalized line and sample Uc, Vc as ratio of
418  // polynomials Pu, Qu and Pv, Qv:
419  //***
420  Pu = polynomial(nlat, nlon, nhgt, theLineNumCoef);
421  Qu = polynomial(nlat, nlon, nhgt, theLineDenCoef);
422  Pv = polynomial(nlat, nlon, nhgt, theSampNumCoef);
423  Qv = polynomial(nlat, nlon, nhgt, theSampDenCoef);
424  Uc = Pu/Qu;
425  Vc = Pv/Qv;
426 
427  //***
428  // Compute residuals between desired and computed line, sample:
429  //***
430  deltaU = U - Uc;
431  deltaV = V - Vc;
432 
433  //***
434  // Check for convergence and skip re-linearization if converged:
435  //***
436  if ((fabs(deltaU) > epsilonU) || (fabs(deltaV) > epsilonV))
437  {
438  //***
439  // Analytically compute the partials of each polynomial wrt lat, lon:
440  //***
441  dPu_dLat = dPoly_dLat(nlat, nlon, nhgt, theLineNumCoef);
442  dQu_dLat = dPoly_dLat(nlat, nlon, nhgt, theLineDenCoef);
443  dPv_dLat = dPoly_dLat(nlat, nlon, nhgt, theSampNumCoef);
444  dQv_dLat = dPoly_dLat(nlat, nlon, nhgt, theSampDenCoef);
445  dPu_dLon = dPoly_dLon(nlat, nlon, nhgt, theLineNumCoef);
446  dQu_dLon = dPoly_dLon(nlat, nlon, nhgt, theLineDenCoef);
447  dPv_dLon = dPoly_dLon(nlat, nlon, nhgt, theSampNumCoef);
448  dQv_dLon = dPoly_dLon(nlat, nlon, nhgt, theSampDenCoef);
449 
450  //***
451  // Analytically compute partials of quotients U and V wrt lat, lon:
452  //***
453  dU_dLat = (Qu*dPu_dLat - Pu*dQu_dLat)/(Qu*Qu);
454  dU_dLon = (Qu*dPu_dLon - Pu*dQu_dLon)/(Qu*Qu);
455  dV_dLat = (Qv*dPv_dLat - Pv*dQv_dLat)/(Qv*Qv);
456  dV_dLon = (Qv*dPv_dLon - Pv*dQv_dLon)/(Qv*Qv);
457 
458  W = dU_dLon*dV_dLat - dU_dLat*dV_dLon;
459 
460  //***
461  // Now compute the corrections to normalized lat, lon:
462  //***
463  deltaLat = (dU_dLon*deltaV - dV_dLon*deltaU) / W;
464  deltaLon = (dV_dLat*deltaU - dU_dLat*deltaV) / W;
465  nlat += deltaLat;
466  nlon += deltaLon;
467  }
468 
469  iteration++;
470 
471  } while (((fabs(deltaU)>epsilonU) || (fabs(deltaV)>epsilonV))
472  && (iteration < MAX_NUM_ITERATIONS));
473 
474  //***
475  // Test for exceeding allowed number of iterations. Flag error if so:
476  //***
477  if (iteration == MAX_NUM_ITERATIONS)
478  {
479  ossimNotify(ossimNotifyLevel_WARN) << "WARNING ossimRpcProjection::lineSampleHeightToWorld: \nMax number of iterations reached in ground point "
480  << "solution. Results are inaccurate." << endl;
481  }
482 
483  //***
484  // Now un-normalize the ground point lat, lon and establish return quantity:
485  //***
486  gpt.lat = nlat*theLatScale + theLatOffset;
487  gpt.lon = nlon*theLonScale + theLonOffset;
488  gpt.hgt = ellHeight;
489 
490 }
491 
493 {
494  return ossimGpt(theLatOffset,
495  theLonOffset,
496  theHgtOffset);
497 }
498 
499 
501 {
502  ossimDpt result;
503 
504 // ossimDpt left = ossimDpt(theSampOffset-1,
505 // theLineOffset);
506 // ossimDpt right = ossimDpt(theSampOffset+1,
507 // theLineOffset);
509  theLineOffset-1);
511  theLineOffset+1);
512 // ossimGpt leftG;
513 // ossimGpt rightG;
514  ossimGpt topG;
515  ossimGpt bottomG;
516 
517 // lineSampleToWorld(left, leftG);
518 // lineSampleToWorld(right, rightG);
519  lineSampleToWorld(top, topG);
520  lineSampleToWorld(bottom, bottomG);
521 
522 // result.x = (ossimEcefPoint(leftG) - ossimEcefPoint(rightG)).magnitude()/2.0;
523  result.y = (ossimEcefPoint(topG) - ossimEcefPoint(bottomG)).magnitude()/2.0;
524  result.x = result.y;
525 
526  return result;
527 }
528 
529 bool ossimRpcProjection::operator==(const ossimProjection& projection) const
530 {
531  if(&projection == this) return true;
532 
533  // not implemented yet
534  //
535  return false;
536 }
537 
538 //*****************************************************************************
539 // PRIVATE METHOD: ossimRpcProjection::polynomial
540 //
541 // Computes polynomial.
542 //
543 //*****************************************************************************
544 double ossimRpcProjection::polynomial(const double& P, const double& L,
545  const double& H, const double* c) const
546 {
547  double r;
548 
549  if (thePolyType == A)
550  {
551  r = c[ 0] + c[ 1]*L + c[ 2]*P + c[ 3]*H +
552  c[ 4]*L*P + c[ 5]*L*H + c[ 6]*P*H + c[ 7]*L*P*H +
553  c[ 8]*L*L + c[ 9]*P*P + c[10]*H*H + c[11]*L*L*L +
554  c[12]*L*L*P + c[13]*L*L*H + c[14]*L*P*P + c[15]*P*P*P +
555  c[16]*P*P*H + c[17]*L*H*H + c[18]*P*H*H + c[19]*H*H*H;
556  }
557  else
558  {
559  r = c[ 0] + c[ 1]*L + c[ 2]*P + c[ 3]*H +
560  c[ 4]*L*P + c[ 5]*L*H + c[ 6]*P*H + c[ 7]*L*L +
561  c[ 8]*P*P + c[ 9]*H*H + c[10]*L*P*H + c[11]*L*L*L +
562  c[12]*L*P*P + c[13]*L*H*H + c[14]*L*L*P + c[15]*P*P*P +
563  c[16]*P*H*H + c[17]*L*L*H + c[18]*P*P*H + c[19]*H*H*H;
564  }
565 
566  return r;
567 }
568 
569 //*****************************************************************************
570 // PRIVATE METHOD: ossimRpcProjection::dPoly_dLat
571 //
572 // Computes derivative of polynomial wrt normalized Latitude P.
573 //
574 //*****************************************************************************
575 double ossimRpcProjection::dPoly_dLat(const double& P, const double& L,
576  const double& H, const double* c) const
577 {
578  double dr;
579 
580  if (thePolyType == A)
581  {
582  dr = c[2] + c[4]*L + c[6]*H + c[7]*L*H + 2*c[9]*P + c[12]*L*L +
583  2*c[14]*L*P + 3*c[15]*P*P +2*c[16]*P*H + c[18]*H*H;
584  }
585  else
586  {
587  dr = c[2] + c[4]*L + c[6]*H + 2*c[8]*P + c[10]*L*H + 2*c[12]*L*P +
588  c[14]*L*L + 3*c[15]*P*P + c[16]*H*H + 2*c[18]*P*H;
589  }
590 
591  return dr;
592 }
593 
594 //*****************************************************************************
595 // PRIVATE METHOD: ossimRpcProjection::dPoly_dLon
596 //
597 // Computes derivative of polynomial wrt normalized Longitude L.
598 //
599 //*****************************************************************************
600 double ossimRpcProjection::dPoly_dLon(const double& P, const double& L,
601  const double& H, const double* c) const
602 {
603  double dr;
604 
605  if (thePolyType == A)
606  {
607  dr = c[1] + c[4]*P + c[5]*H + c[7]*P*H + 2*c[8]*L + 3*c[11]*L*L +
608  2*c[12]*L*P + 2*c[13]*L*H + c[14]*P*P + c[17]*H*H;
609  }
610  else
611  {
612  dr = c[1] + c[4]*P + c[5]*H + 2*c[7]*L + c[10]*P*H + 3*c[11]*L*L +
613  c[12]*P*P + c[13]*H*H + 2*c[14]*P*L + 2*c[17]*L*H;
614  }
615  return dr;
616 }
617 
618 //*****************************************************************************
619 // METHOD: ossimRpcProjection::print()
620 //
621 // Formatted dump of data members.
622 //
623 //*****************************************************************************
625 {
626  out << "\nDump of ossimRpcProjection object at " << hex << this << ":\n"
627  << POLY_TYPE_KW << ": " << thePolyType << "\n"
628  << LINE_SCALE_KW << ": " << theLineScale << "\n"
629  << SAMP_SCALE_KW << ": " << theSampScale << "\n"
630  << LAT_SCALE_KW << ": " << theLatScale << "\n"
631  << LON_SCALE_KW << ": " << theLonScale << "\n"
632  << HGT_SCALE_KW << ": " << theHgtScale << "\n"
633  << LINE_OFFSET_KW << ": " << theLineOffset << "\n"
634  << SAMP_OFFSET_KW << ": " << theSampOffset << "\n"
635  << LAT_OFFSET_KW << ": " << theLatOffset << "\n"
636  << LON_OFFSET_KW << ": " << theLonOffset << "\n"
637  << HGT_OFFSET_KW << ": " << theHgtOffset << endl;
638 
639  for (int i=0; i<NUM_COEFFS; i++)
640  out<<" "<<LINE_NUM_COEF_KW<<"["<<i<<"]: "<<theLineNumCoef[i]<<endl;
641 
642  out << endl;
643  for (int i=0; i<NUM_COEFFS; i++)
644  out<<" "<<LINE_DEN_COEF_KW<<"["<<i<<"]: "<<theLineDenCoef[i]<<endl;
645 
646  out << endl;
647  for (int i=0; i<NUM_COEFFS; i++)
648  out<<" "<<SAMP_NUM_COEF_KW<<"["<<i<<"]: "<<theSampNumCoef[i]<<endl;
649 
650  out << endl;
651  for (int i=0; i<NUM_COEFFS; i++)
652  out<<" "<<SAMP_DEN_COEF_KW<<"["<<i<<"]: "<<theSampDenCoef[i]<<endl;
653 
654  out << endl;
655 
656  return ossimProjection::print(out);
657 }
658 
659 //*****************************************************************************
660 // METHOD: ossimRpcProjection::saveState()
661 //
662 // Saves the model state to the KWL. This KWL also serves as a geometry file.
663 //
664 //*****************************************************************************
666  const char* prefix) const
667 {
668  if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimRpcProjection::saveState(): entering..." << std::endl;
669 
670  kwl.add(prefix, ossimKeywordNames::TYPE_KW, MODEL_TYPE);
671 
672  //***
673  // Hand off to base class for common stuff:
674  //***
675  ossimProjection::saveState(kwl, prefix);
676 
677  kwl.add(prefix,
678  POLY_TYPE_KW,
679  (char)thePolyType,
680  true);
681 
682  kwl.add(prefix, LINE_SCALE_KW, theLineScale);
683  kwl.add(prefix, SAMP_SCALE_KW, theSampScale);
684  kwl.add(prefix, LAT_SCALE_KW, theLatScale);
685  kwl.add(prefix, LON_SCALE_KW, theLonScale);
686  kwl.add(prefix, HGT_SCALE_KW, theHgtScale);
687  kwl.add(prefix, LINE_OFFSET_KW, theLineOffset);
688  kwl.add(prefix, SAMP_OFFSET_KW, theSampOffset);
689  kwl.add(prefix, LAT_OFFSET_KW, theLatOffset);
690  kwl.add(prefix, LON_OFFSET_KW, theLonOffset);
691 
692  kwl.add(prefix, HGT_OFFSET_KW, theHgtOffset);
693 
694  for (int i=0; i<NUM_COEFFS; i++)
695  {
696  kwl.add(prefix, (LINE_NUM_COEF_KW + ossimString::toString(i)).c_str(), theLineNumCoef[i]);
697  kwl.add(prefix, (LINE_DEN_COEF_KW + ossimString::toString(i)).c_str(), theLineDenCoef[i]);
698  kwl.add(prefix, (SAMP_NUM_COEF_KW + ossimString::toString(i)).c_str(), theSampNumCoef[i]);
699  kwl.add(prefix, (SAMP_DEN_COEF_KW + ossimString::toString(i)).c_str(), theSampDenCoef[i]);
700  }
701 
702  saveAdjustments(kwl, prefix);
703 
704  if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimRpcProjection::saveState(): returning..." << std::endl;
705  return true;
706 }
707 
708 //*****************************************************************************
709 // METHOD: ossimRpcProjection::loadState()
710 //
711 // Restores the model's state from the KWL. This KWL also serves as a
712 // geometry file.
713 //
714 //*****************************************************************************
716  const char* prefix)
717 {
718  if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimRpcProjection::loadState(): entering..." << std::endl;
719 
720  const char* value;
721  const char* keyword;
722 
723  //***
724  // Pass on to the base-class for parsing first:
725  //***
726  bool success = ossimProjection::loadState(kwl, prefix);
727  if (!success)
728  {
729  theErrorStatus++;
730  if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimRpcProjection::loadState(): returning with error..." << std::endl;
731  return false;
732  }
733 
734  //***
735  // Continue parsing for local members:
736  //***
737  keyword = POLY_TYPE_KW;
738  value = kwl.find(prefix, keyword);
739  if (!value)
740  {
741  ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimRpcProjection::loadState(): Error encountered parsing the following required keyword: "
742  << "<" << keyword << ">. Check the keywordlist for proper syntax."
743  << std::endl;
744  return false;
745  }
746  thePolyType = (PolynomialType) value[0];
747 
748  keyword = LINE_SCALE_KW;
749  value = kwl.find(prefix, keyword);
750  if (!value)
751  {
752  ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimRpcProjection::loadState(): Error encountered parsing the following required keyword: "
753  << "<" << keyword << ">. Check the keywordlist for proper syntax."
754  << std::endl;
755  return false;
756  }
757  theLineScale = ossimString(value).toDouble();
758 
759  keyword = SAMP_SCALE_KW;
760  value = kwl.find(prefix, keyword);
761  if (!value)
762  {
763  ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimRpcProjection::loadState(): Error encountered parsing the following required keyword: "
764  << "<" << keyword << ">. Check the keywordlist for proper syntax."
765  << std::endl;
766  return false;
767  }
768  theSampScale = ossimString(value).toDouble();
769 
770  keyword = LAT_SCALE_KW;
771  value = kwl.find(prefix, keyword);
772  if (!value)
773  {
774  ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimRpcProjection::loadState(): Error encountered parsing the following required keyword: "
775  << "<" << keyword << ">. Check the keywordlist for proper syntax."
776  << std::endl;
777  return false;
778  }
779  theLatScale = ossimString(value).toDouble();
780 
781  keyword = LON_SCALE_KW;
782  value = kwl.find(prefix, keyword);
783  if (!value)
784  {
785  ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimRpcProjection::loadState(): Error encountered parsing the following required keyword: "
786  << "<" << keyword << ">. Check the keywordlist for proper syntax."
787  << std::endl;
788  return false;
789  }
790  theLonScale = ossimString(value).toDouble();
791 
792  keyword = HGT_SCALE_KW;
793  value = kwl.find(prefix, keyword);
794  if (!value)
795  {
796  ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimRpcProjection::loadState(): Error encountered parsing the following required keyword: "
797  << "<" << keyword << ">. Check the keywordlist for proper syntax."
798  << std::endl;
799  return false;
800  }
801  theHgtScale = ossimString(value).toDouble();
802 
803  keyword = LINE_OFFSET_KW;
804  value = kwl.find(prefix, keyword);
805  if (!value)
806  {
807  ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimRpcProjection::loadState(): Error encountered parsing the following required keyword: "
808  << "<" << keyword << ">. Check the keywordlist for proper syntax."
809  << std::endl;
810  return false;
811  }
813 
814  keyword = SAMP_OFFSET_KW;
815  value = kwl.find(prefix, keyword);
816  if (!value)
817  {
818  ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimRpcProjection::loadState(): Error encountered parsing the following required keyword: "
819  << "<" << keyword << ">. Check the keywordlist for proper syntax."
820  << std::endl;
821  return false;
822  }
824 
825  keyword = LAT_OFFSET_KW;
826  value = kwl.find(prefix, keyword);
827  if (!value)
828  {
829  ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimRpcProjection::loadState(): Error encountered parsing the following required keyword: "
830  << "<" << keyword << ">. Check the keywordlist for proper syntax."
831  << std::endl;
832  return false;
833  }
834  theLatOffset = ossimString(value).toDouble();
835 
836  keyword = LON_OFFSET_KW;
837  value = kwl.find(prefix, keyword);
838  if (!value)
839  {
840  ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimRpcProjection::loadState(): Error encountered parsing the following required keyword: "
841  << "<" << keyword << ">. Check the keywordlist for proper syntax."
842  << std::endl;
843  return false;
844  }
845  theLonOffset = ossimString(value).toDouble();
846 
847  keyword = HGT_OFFSET_KW;
848  value = kwl.find(prefix, keyword);
849  if (!value)
850  {
851  ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimRpcProjection::loadState(): Error encountered parsing the following required keyword: "
852  << "<" << keyword << ">. Check the keywordlist for proper syntax."
853  << std::endl;
854  return false;
855  }
856  theHgtOffset = ossimString(value).toDouble();
857 
858  for (int i=0; i<NUM_COEFFS; i++)
859  {
860  value = kwl.find(prefix, (LINE_NUM_COEF_KW+ossimString::toString(i)).c_str());
861  if (!value)
862  {
863  ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimRpcProjection::loadState(): Error encountered parsing the following required keyword: "
864  << "<" << keyword << ">. Check the keywordlist for proper syntax."
865  << std::endl;
866  return false;
867  }
868  theLineNumCoef[i] = ossimString(value).toDouble();
869 
870  value = kwl.find(prefix, (LINE_DEN_COEF_KW+ossimString::toString(i)).c_str());
871  if (!value)
872  {
873  ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimRpcProjection::loadState(): Error encountered parsing the following required keyword: "
874  << "<" << keyword << ">. Check the keywordlist for proper syntax."
875  << std::endl;
876  return false;
877  }
878  theLineDenCoef[i] = ossimString(value).toDouble();
879 
880  value = kwl.find(prefix, (SAMP_NUM_COEF_KW+ossimString::toString(i)).c_str());
881  if (!value)
882  {
883  ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimRpcProjection::loadState(): Error encountered parsing the following required keyword: "
884  << "<" << keyword << ">. Check the keywordlist for proper syntax."
885  << std::endl;
886  return false;
887  }
888  theSampNumCoef[i] = ossimString(value).toDouble();
889 
890  value = kwl.find(prefix, (SAMP_DEN_COEF_KW+ossimString::toString(i)).c_str());
891  if (!value)
892  {
893  ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimRpcProjection::loadState(): Error encountered parsing the following required keyword: "
894  << "<" << keyword << ">. Check the keywordlist for proper syntax."
895  << std::endl;
896  return false;
897  }
898  theSampDenCoef[i] = ossimString(value).toDouble();
899  }
900 
901  if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimRpcProjection::loadState(): returning..." << std::endl;
902 
903  return true;
904 }
905 
907 {
908  resizeAdjustableParameterArray(NUM_ADJUSTABLE_PARAMS);
909  int numParams = getNumberOfAdjustableParameters();
910  for (int i=0; i<numParams; i++)
911  {
912  setAdjustableParameter(i, 0.0);
913  setParameterDescription(i, PARAM_NAMES[i]);
914  setParameterUnit(i,PARAM_UNITS[i]);
915  }
916  setParameterSigma(INTRACK_OFFSET, 50.0);
917  setParameterSigma(CRTRACK_OFFSET, 50.0);
918  setParameterSigma(INTRACK_SCALE, 50.0);
919  setParameterSigma(CRTRACK_SCALE, 50.0);
920  setParameterSigma(MAP_ROTATION, 0.1);
921 // setParameterSigma(YAW_OFFSET, 0.001);
922 }
923 
925 {
926  theIntrackOffset = computeParameterOffset(INTRACK_OFFSET);
927  theCrtrackOffset = computeParameterOffset(CRTRACK_OFFSET);
928  theIntrackScale = computeParameterOffset(INTRACK_SCALE);
929  theCrtrackScale = computeParameterOffset(CRTRACK_SCALE);
930  double mapRotation = computeParameterOffset(MAP_ROTATION);
931  theCosMapRot = ossim::cosd(mapRotation);
932  theSinMapRot = ossim::sind(mapRotation);
933 }
934 
935 bool
937 {
938  ossimKeywordlist kwl;
939 
940  if(kwl.addFile(ossimFilename(setup)))
941  {
942  return loadState(kwl);
943  }
944  else
945  {
947  if(proj.valid())
948  {
949  kwl.clear();
950  proj->saveState(kwl);
951 
952  return loadState(kwl);
953  }
954  }
955 
956  return false;
957 }
958 
961 {
962  ossim_uint32 dof = 0;
963  ossim_uint32 idx = 0;
965  for(idx = 0; idx < numAdj; ++idx)
966  {
967  if(!isParameterLocked(idx))
968  {
969  ++dof;
970  }
971  }
972 
973  return dof;
974 }
975 //give inverse() partial derivative regarding parameter parmIdx (>=0)
976 ossimGpt
977 ossimRpcProjection::getInverseDeriv(int parmIdx, const ossimDpt& ipos, double hdelta)
978 {
979  double den = 0.5/hdelta;
980  ossimGpt res,gd;
981 
982  double middle = getAdjustableParameter(parmIdx);
983  //set parm to high value
984  setAdjustableParameter(parmIdx, middle + hdelta, true);
985  res = inverse(ipos);
986  //set parm to low value and gte difference
987  setAdjustableParameter(parmIdx, middle - hdelta, true);
988  gd = inverse(ipos);
989 
990  //reset parm
991  setAdjustableParameter(parmIdx, middle, true);
992 
993  res.lon = den*(res.lon - gd.lon) * 100000.0; //TBC : approx meters
994  res.lat = den*(res.lat - gd.lat) * 100000.0 * cos(gd.lat / 180.0 * M_PI);
995  res.hgt = den*(res.hgt - gd.hgt);
996 
997  return res;
998 }
999 
1000 //give forward() partial derivative regarding parameter parmIdx (>=0)
1001 ossimDpt
1002 ossimRpcProjection::getForwardDeriv(int parmIdx, const ossimGpt& gpos, double hdelta)
1003 {
1004  static double den = 0.5/hdelta;
1005  ossimDpt res;
1006 
1007  double middle = getAdjustableParameter(parmIdx);
1008  //set parm to high value
1009  setAdjustableParameter(parmIdx, middle + hdelta, true);
1010  res = forward(gpos);
1011  //set parm to low value and gte difference
1012  setAdjustableParameter(parmIdx, middle - hdelta, true);
1013  res -= forward(gpos);
1014  //get partial derivative
1015  res = res*den;
1016 
1017  //reset parm
1018  setAdjustableParameter(parmIdx, middle, true);
1019 
1020  return res;
1021 }
1022 
1023 double
1024 ossimRpcProjection::optimizeFit(const ossimTieGptSet& tieSet, double* /* targetVariance */)
1025 {
1026  //NOTE : ignore targetVariance
1027  ossimRefPtr<ossimRpcSolver> solver = new ossimRpcSolver(false, false); //TBD : choices should be part of setupFromString
1028 
1029  std::vector<ossimDpt> imagePoints;
1030  std::vector<ossimGpt> groundPoints;
1031  tieSet.getSlaveMasterPoints(imagePoints, groundPoints);
1032  solver->solveCoefficients(imagePoints, groundPoints);
1033 
1034  const ossimRefPtr< ossimRpcModel > optProj = solver->getRpcModel();
1035  if (!optProj)
1036  {
1037  ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimRpcProjection::optimizeFit(): error when optimizing the RPC with given tie points"
1038  << std::endl;
1039  return -1.0;
1040  }
1041 
1042  ossimKeywordlist kwl;
1043  optProj->saveState(kwl);
1044  this->loadState(kwl);
1045 
1046  return std::pow(solver->getRmsError(), 2); //variance in pixel^2
1047 }
1048 
1049 void
1051  NEWMAT::SymmetricMatrix& A,
1052  NEWMAT::ColumnVector& residue,
1053  NEWMAT::ColumnVector& projResidue,
1054  double pstep_scale)
1055 {
1056  //goal: build Least Squares system
1057  //constraint: never store full Jacobian matrix in memory (can be huge)
1058  // so we build the matrices incrementally
1059  // the system can be built using forward() or inverse() depending on the projection capabilities : useForward()
1060  //
1061  //TBD : add covariance matrix for each tie point
1062 
1063  //init
1065  int dimObs;
1066  bool useImageObs = useForward(); //caching
1067  if (useImageObs)
1068  {
1069  dimObs = 2; //image observation
1070  } else {
1071  dimObs = 3; //ground observations
1072  }
1073  int no = dimObs * tieSet.size(); //number of observations
1074 
1075  A.ReSize(np);
1076  residue.ReSize(no);
1077  projResidue.ReSize(np);
1078  //Zeroify matrices that will be accumulated
1079  A = 0.0;
1080  projResidue = 0.0;
1081 
1082  const vector<ossimRefPtr<ossimTieGpt> >& theTPV = tieSet.getTiePoints();
1083  vector<ossimRefPtr<ossimTieGpt> >::const_iterator tit;
1084  unsigned long c=1;
1085 
1086  if (useImageObs)
1087  {
1088  //image observations
1089  ossimDpt* imDerp = new ossimDpt[np];
1090  ossimDpt resIm;
1091  // loop on tie points
1092  for (tit = theTPV.begin() ; tit != theTPV.end() ; ++tit)
1093  {
1094  //compute residue
1095  resIm = (*tit)->tie - forward(*(*tit));
1096  residue(c++) = resIm.x;
1097  residue(c++) = resIm.y;
1098 
1099  //compute all image derivatives regarding parametres for the tie point position
1100  for(int p=0;p<np;++p)
1101  {
1102  imDerp[p] = getForwardDeriv( p , *(*tit) , pstep_scale);
1103  }
1104 
1105  //compute influence of tie point on all sytem elements
1106  for(int p1=0;p1<np;++p1)
1107  {
1108  //proj residue: J * residue
1109  projResidue.element(p1) += imDerp[p1].x * resIm.x + imDerp[p1].y * resIm.y;
1110 
1111  //normal matrix A = transpose(J)*J
1112  for(int p2=p1;p2<np;++p2)
1113  {
1114  A.element(p1,p2) += imDerp[p1].x * imDerp[p2].x + imDerp[p1].y * imDerp[p2].y;
1115  }
1116  }
1117  }
1118  delete []imDerp;
1119  }
1120  else
1121  {
1122  // ground observations
1123  std::vector<ossimGpt> gdDerp(np);
1124  ossimGpt gd, resGd;
1125  // loop on tie points
1126  for (tit = theTPV.begin() ; tit != theTPV.end() ; ++tit)
1127  {
1128  //compute residue
1129  gd = inverse((*tit)->tie);
1130  residue(c++) = resGd.lon = ((*tit)->lon - gd.lon) * 100000.0;
1131  residue(c++) = resGd.lat = ((*tit)->lat - gd.lat) * 100000.0 * cos(gd.lat / 180.0 * M_PI);
1132  residue(c++) = resGd.hgt = (*tit)->hgt - gd.hgt; //TBD : normalize to meters?
1133 
1134  //compute all image derivatives regarding parametres for the tie point position
1135  for(int p=0;p<np;++p)
1136  {
1137  gdDerp[p] = getInverseDeriv( p , (*tit)->tie, pstep_scale);
1138  }
1139 
1140  //compute influence of tie point on all sytem elements
1141  for(int p1=0;p1<np;++p1)
1142  {
1143  //proj residue: J * residue
1144  projResidue.element(p1) += gdDerp[p1].lon * resGd.lon + gdDerp[p1].lat * resGd.lat + gdDerp[p1].hgt * resGd.hgt; //TBC
1145 
1146  //normal matrix A = transpose(J)*J
1147  for(int p2=p1;p2<np;++p2)
1148  {
1149  A.element(p1,p2) += gdDerp[p1].lon * gdDerp[p2].lon + gdDerp[p1].lat * gdDerp[p2].lat + gdDerp[p1].hgt * gdDerp[p2].hgt;
1150  }
1151  }
1152  }
1153  } //end of if (useImageObs)
1154 }
1155 
1156 NEWMAT::ColumnVector
1158 {
1159  //init
1160  NEWMAT::ColumnVector residue;
1161  int dimObs;
1162 
1163  bool useImageObs = useForward(); //caching
1164  if (useImageObs)
1165  {
1166  dimObs = 2; //image observation
1167  } else {
1168  dimObs = 3; //ground observations
1169  }
1170  int no = dimObs * tieSet.size(); //number of observations
1171 
1172  residue.ReSize(no);
1173 
1174  const vector<ossimRefPtr<ossimTieGpt> >& theTPV = tieSet.getTiePoints();
1175  vector<ossimRefPtr<ossimTieGpt> >::const_iterator tit;
1176  unsigned long c=1;
1177 
1178  if (useImageObs)
1179  {
1180  //image observations
1181  ossimDpt resIm;
1182  // loop on tie points
1183  for (tit = theTPV.begin() ; tit != theTPV.end() ; ++tit)
1184  {
1185  //compute residue
1186  resIm = (*tit)->tie - forward(**tit);
1187  residue(c++) = resIm.x;
1188  residue(c++) = resIm.y;
1189  }
1190  } else {
1191  // ground observations
1192  ossimGpt gd;
1193  // loop on tie points
1194  for (tit = theTPV.begin() ; tit != theTPV.end() ; ++tit)
1195  {
1196  //compute residue
1197  gd = inverse((*tit)->tie);
1198  residue(c++) = ((*tit)->lon - gd.lon) * 100000.0; //approx meters //TBC TBD
1199  residue(c++) = ((*tit)->lat - gd.lat) * 100000.0 * cos(gd.lat / 180.0 * M_PI);
1200  residue(c++) = (*tit)->hgt - gd.hgt; //meters
1201  }
1202  } //end of if (useImageObs)
1203 
1204  return residue;
1205 }
1206 
1212 NEWMAT::ColumnVector
1213 ossimRpcProjection::solveLeastSquares(NEWMAT::SymmetricMatrix& A, NEWMAT::ColumnVector& r)const
1214 {
1215  NEWMAT::ColumnVector x = invert(A)*r;
1216  return x;
1217 }
1218 
1222 NEWMAT::Matrix
1223 ossimRpcProjection::invert(const NEWMAT::Matrix& m)const
1224 {
1225  ossim_uint32 idx = 0;
1226  NEWMAT::DiagonalMatrix d;
1227  NEWMAT::Matrix u;
1228  NEWMAT::Matrix v;
1229 
1230  // decompose m.t*m which is stored in Temp into the singular values and vectors.
1231  //
1232  NEWMAT::SVD(m, d, u, v, true, true);
1233 
1234  // invert the diagonal
1235  // this is just doing the reciprical fo all diagonal components and store back int
1236  // d. ths compute d inverse.
1237  //
1238  for(idx=0; idx < (ossim_uint32)d.Ncols(); ++idx)
1239  {
1240  if(d[idx] > 1e-14) //TBC : use DBL_EPSILON ?
1241  {
1242  d[idx] = 1.0/d[idx];
1243  }
1244  else
1245  {
1246  d[idx] = 0.0;
1247 
1248 //DEBUG TBR
1249 cout<<"warning: singular matrix in SVD"<<endl;
1250 
1251  }
1252  }
1253 
1254  //compute inverse of decomposed m;
1255  return v*d*u.t();
1256 }
ossim_uint32 x
void setParameterDescription(ossim_uint32 idx, const ossimString &descrption)
virtual ossimDpt getMetersPerPixel() const
unsigned int size() const
NEWMAT::Matrix invert(const NEWMAT::Matrix &m) const
stable invert stolen from ossimRpcSolver
bool saveAdjustments(ossimKeywordlist &kwl, const ossimString &prefix=ossimString("")) const
Save all adjustments to the KWL file.
void getSlaveMasterPoints(std::vector< ossimDpt > &imv, std::vector< ossimGpt > &gdv) const
virtual void adjustableParametersChanged()
Represents serializable keyword/value map.
bool addFile(const char *file)
bool isLonNan() const
Definition: ossimGpt.h:140
bool valid() const
Definition: ossimRefPtr.h:75
virtual bool setupOptimizer(const ossimString &setup)
setupFromString() Derived classes should implement as needed. Initialize parameters needed for optimi...
const char * find(const char *key) const
double samp
Definition: ossimDpt.h:164
char theLineScale[LINE_SCALE_SIZE+1]
FIELD: LINE_SCALE.
virtual std::ostream & print(std::ostream &out) const
Outputs theErrorStatus as an ossimErrorCode and an ossimString.
virtual ossimOptimizableProjection & operator=(const ossimOptimizableProjection &source)
NEWMAT::ColumnVector getResidue(const ossimTieGptSet &tieSet)
double y
Definition: ossimDpt.h:165
ossimRpcProjection & operator=(const ossimRpcProjection &source)
virtual ossimGpt inverse(const ossimDpt &pp) const
void makeNan()
Definition: ossimGpt.h:130
static ossimString toString(bool aValue)
Numeric to string methods.
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
virtual void lineSampleHeightToWorld(const ossimDpt &image_point, const double &heightEllipsoid, ossimGpt &worldPoint) const
virtual ossimDpt getForwardDeriv(int parmIdx, const ossimGpt &gpos, double hdelta=1e-11)
ossim_float64 hgt
Height in meters above the ellipsiod.
Definition: ossimGpt.h:274
double sind(double x)
Definition: ossimCommon.h:260
virtual bool operator==(const ossimProjection &projection) const
bool isLatNan() const
Definition: ossimGpt.h:139
void solveCoefficients(const ossimDrect &imageBounds, ossimProjection *imageProj, ossim_uint32 xSamples=8, ossim_uint32 ySamples=8)
This will convert any projector to an RPC model.
#define A(r, c)
static const char * TYPE_KW
const ossimRefPtr< ossimRpcModel > getRpcModel() const
Fetches the solved-for RPC model.
virtual std::ostream & print(std::ostream &out) const
double dPoly_dLat(const double &nlat, const double &nlon, const double &nhgt, const double *coeffs) const
double ossim_float64
void add(const char *prefix, const ossimKeywordlist &kwl, bool overwrite=true)
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
virtual class enabling projection optimization (can be used for outlier rejection - RANSAC) ...
double line
Definition: ossimDpt.h:165
ossimProjection * createProjection(const ossimFilename &filename, ossim_uint32 entryIdx) const
#define M_PI
ossim_float64 lon
Definition: ossimGpt.h:266
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
saveState Fulfills ossimObject base-class pure virtuals.
virtual ossimGpt origin() const
virtual void lineSampleToWorld(const ossimDpt &image_point, ossimGpt &world_point) const
unsigned int ossim_uint32
double height() const
Definition: ossimGpt.h:107
double toDouble() const
virtual bool useForward() const
void SVD(const Matrix &, DiagonalMatrix &, Matrix &, Matrix &, bool=true, bool=true)
Definition: svd.cpp:26
void setParameterUnit(ossim_uint32 idx, ossimUnitType unit)
const vector< ossimRefPtr< ossimTieGpt > > & getTiePoints() const
double cosd(double x)
Definition: ossimCommon.h:259
bool hasNans() const
Definition: ossimDpt.h:67
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
NEWMAT::ColumnVector solveLeastSquares(NEWMAT::SymmetricMatrix &A, NEWMAT::ColumnVector &r) const
double getRmsError() const
static ossimProjectionFactoryRegistry * instance()
virtual double optimizeFit(const ossimTieGptSet &tieSet, double *targetVariance=NULL)
virtual ossimObject * getBaseObject()
virtual ossimGpt getInverseDeriv(int parmIdx, const ossimDpt &ipos, double hdelta=1e-11)
PolynomialType thePolyType
double polynomial(const double &nlat, const double &nlon, const double &nhgt, const double *coeffs) const
virtual void worldToLineSample(const ossimGpt &world_point, ossimDpt &image_point) const
virtual ossim_uint32 degreesOfFreedom() const
virtual ossimDpt forward(const ossimGpt &wp) const
void buildNormalEquation(const ossimTieGptSet &tieSet, NEWMAT::SymmetricMatrix &A, NEWMAT::ColumnVector &residue, NEWMAT::ColumnVector &projResidue, double pstep_scale)
virtual void setAdjustableParameter(ossim_uint32 idx, double value, bool notify=false)
storage class for a set of geographic tie points, between master and slave images ...
double dPoly_dLon(const double &nlat, const double &nlon, const double &nhgt, const double *coeffs) const
double x
Definition: ossimDpt.h:164
void resizeAdjustableParameterArray(ossim_uint32 numberOfParameters)
This currently only support Rational poilynomial B format.
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
RTTI_DEF3(ossimRpcProjection, "ossimRpcProjection", ossimProjection, ossimOptimizableProjection, ossimAdjustableParameterInterface)
char theLineOffset[LINE_OFFSET_SIZE+1]
FIELD: LINE_OFF.
ossim_float64 lat
Definition: ossimGpt.h:265
void setAttributes(ossim_float64 theSampleOffset, ossim_float64 theLineOffset, ossim_float64 theSampleScale, ossim_float64 theLineScale, ossim_float64 theLatOffset, ossim_float64 theLonOffset, ossim_float64 theHeightOffset, ossim_float64 theLatScale, ossim_float64 theLonScale, ossim_float64 theHeightScale, const std::vector< double > &xNumeratorCoeffs, const std::vector< double > &xDenominatorCoeffs, const std::vector< double > &yNumeratorCoeffs, const std::vector< double > &yDenominatorCoeffs, PolynomialType polyType=B)
void setParameterSigma(ossim_uint32 idx, double value, bool notify=false)
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
void makeNan()
Definition: ossimDpt.h:65
std::basic_ostream< char > ostream
Base class for char output streams.
Definition: ossimIosFwd.h:23
int ossim_int32
bool isnan(const float &v)
isnan Test for floating point Not A Number (NAN) value.
Definition: ossimCommon.h:91