15 using namespace ossim;
22 : theUseElevationFlag(useElevation),
23 theHeightAboveMSLFlag(useHeightAboveMSLFlag),
48 std::vector<ossimGpt> groundPoints;
49 std::vector<ossimDpt> imagePoints;
54 ySamples = STARTING_GRID_SIZE;
56 xSamples = STARTING_GRID_SIZE;
58 double Dx = imageBounds.
width()/(xSamples-1);
59 double Dy = imageBounds.
height()/(ySamples-1);
61 for(
y = 0;
y < ySamples; ++
y)
63 dpt.
y =
y*Dy + imageBounds.
ul().
y;
64 for(
x = 0;
x < xSamples; ++
x)
66 dpt.
x =
x*Dx + imageBounds.
ul().
x;
86 imagePoints.push_back(dpt);
87 groundPoints.push_back(gpt);
94 const std::vector<ossimGpt>& groundControlPoints)
96 if((imagePoints.size() != groundControlPoints.size()))
102 int numPoints = imagePoints.size();
103 std::vector<double> fx, fy;
107 std::vector<double>
x;
108 std::vector<double>
y;
109 std::vector<double> z;
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());
127 double heightSum=0.0;
130 for(c = 0; c < groundControlPoints.size();++c)
132 if(
ossim::isnan(groundControlPoints[c].latd()) ==
false)
134 latSum += groundControlPoints[c].latd();
136 if(
ossim::isnan(groundControlPoints[c].lond()) ==
false)
138 lonSum += groundControlPoints[c].lond();
140 if(!groundControlPoints[c].isHgtNan())
144 heightSum += groundControlPoints[c].height();
151 ossimGpt centerGround(latSum/groundControlPoints.size(),
152 lonSum/groundControlPoints.size(),
153 heightSum/groundControlPoints.size());
163 for(c = 0; c < groundControlPoints.size(); ++c)
165 deltaLat = (groundControlPoints[c].latd()-centerGround.latd());
166 deltaLon = (groundControlPoints[c].lond()-centerGround.lond());
167 if(!groundControlPoints[c].isHgtNan())
171 deltaHeight = groundControlPoints[c].
height() - centerGround.height();
172 heightTest = groundControlPoints[c].height();
184 fx[c] = (imagePoints[c].x - centerImagePoint.
x)/(w/2.0);
185 fy[c] = (imagePoints[c].y - centerImagePoint.
y)/(h/2.0);
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);
208 elevationEnabled =
false;
209 if(maxDeltaHeight < 1.0)
210 maxDeltaHeight = 1.0;
213 if(!elevationEnabled)
216 maxDeltaHeight = 10000;
217 centerGround.height(0.0);
220 for(c = 0; c < groundControlPoints.size(); ++c)
224 z[c] /= maxDeltaHeight;
245 NEWMAT::ColumnVector coeffxVec;
246 NEWMAT::ColumnVector coeffyVec;
262 for (
int i=1; i<20; i++)
276 for (idx = 0; idx<imagePoints.size(); idx++)
279 evalPoint(groundControlPoints[idx], evalPt);
283 sumSquareError += (len*len);
292 const double& tolerance)
294 static const char* MODULE =
"ossimRpcSolver::solve() ";
311 bool converged =
false;
315 double sumResiduals = 0;
316 int numResiduals = 0;
323 double deltaX = w/(xSamples-1);
324 double deltaY = h/(ySamples-1);
329 ipt.
y = deltaY*((double)
y + 0.5) + ul.
y;
333 ipt.
x = deltaX*((double)
x + 0.5) + ul.
x;
349 residual = (ipt-irpc).length();
352 sumResiduals += residual;
364 <<
"\n sampling grid size: ("<<xSamples<<
", "<<ySamples<<
")" 371 if ((xSamples >= ENDING_GRID_SIZE) && (ySamples >= ENDING_GRID_SIZE))
377 if (xSamples > ENDING_GRID_SIZE)
378 xSamples = ENDING_GRID_SIZE;
380 if (ySamples > ENDING_GRID_SIZE)
381 ySamples = ENDING_GRID_SIZE;
392 <<
"WARNING: Unable to converge on desired error tolerance ("<<tolerance<<
" p).\n" 399 <<
"WARNING: While the RPC solution did converge, at least one residual (" 400 <<
theMaxResidual<<
") is larger than the desired error tolerance ("<<tolerance<<
" p)." 407 const double& pixel_tolerance)
417 return solve(imageRect, geom.
get(), pixel_tolerance);
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 439 NEWMAT::ColumnVector r((
int)f.size());
440 for(idx = 0; idx < f.size(); ++idx)
446 coeff =
invert(m.t()*m)*m.t()*r;
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 461 NEWMAT::ColumnVector r((
int)f.size());
463 for(idx = 0; idx < f.size(); ++idx)
468 NEWMAT::ColumnVector tempCoeff;
469 NEWMAT::DiagonalMatrix weights((
int)f.size());
470 NEWMAT::ColumnVector denominator(20);
474 for(idx = 0; idx < f.size(); ++idx)
484 w2 = weights*weights;
488 cout<<
"\nw2 = \n"<<w2<<endl;
489 cout<<
"\nr = "<<r<<endl;
501 NEWMAT::Matrix mt = m.t();
502 cout<<
"\nm = "<<m<<endl;
503 cout<<
"\nmt = "<<mt<<endl;
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;
512 NEWMAT::Matrix mtw2m_inv =
invert(mtw2m);
513 cout<<
"\nmtw2m_inv = "<<mtw2m_inv<<endl;
514 tempCoeff = mtw2m_inv * mtw2r;
515 cout<<
"\ntempCoeff = "<<tempCoeff<<endl;
518 tempCoeff =
invert(m.t()*w2*m)*m.t()*w2*r;
522 for(idx = 0; idx < 19; ++idx)
524 denominator[idx+1] = tempCoeff[20+idx];
526 denominator[0] = 1.0;
531 NEWMAT::ColumnVector residual = m.t()*w2*(m*tempCoeff-r);
534 NEWMAT::Matrix tempRes = (residual.t()*residual);
535 residualValue = sqrt(tempRes[0][0]);
539 }
while ((residualValue >
FLT_EPSILON) && (iterations < 10));
547 NEWMAT::DiagonalMatrix d;
577 const NEWMAT::ColumnVector& f,
578 const std::vector<double>&
x,
579 const std::vector<double>&
y,
580 const std::vector<double>& z)
const 583 equations.ReSize(f.Nrows(), 39);
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];
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 636 result.ReSize(f.Nrows());
639 NEWMAT::RowVector row(coefficients.Nrows());
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];
667 result[idx] += row[idx2]*coefficients[idx2];
672 result[idx] = 1.0/result[idx];
PolynomialType thePolyType
virtual void worldToLineSample(const ossimGpt &world_point, ossimDpt &image_point) const
worldToLineSample() Overrides base class implementation.
double theSampNumCoef[20]
void setProjection(ossimProjection *projection)
Sets the projection to be used for local-to-world coordinate transformation.
ossim_float64 width() const
virtual ossimImageHandler * open(const ossimFilename &fileName, bool trySuffixFirst=true, bool openOverview=true) const
open that takes a filename.
ossimRefPtr< ossimNitfRegisteredTag > getNitfRpcBTag() const
This code was derived from https://gist.github.com/mshockwave.
const ossimDpt & ul() const
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.
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.
void changeDatum(const ossimDatum *datum)
This will actually perform a shift.
const ossimDatum * datum() const
datum().
double theSampDenCoef[20]
void evalPoint(const ossimGpt &gpt, ossimDpt &ipt) const
double theLineNumCoef[20]
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
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.
unsigned int ossim_uint32
void SVD(const Matrix &, DiagonalMatrix &, Matrix &, Matrix &, bool=true, bool=true)
ossimRefPtr< ossimRpcModel > theRpcModel
ossim_float64 height() const
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
NEWMAT::Matrix invert(const NEWMAT::Matrix &m) const
Inverts using the SVD method.
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]
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
bool isnan(const float &v)
isnan Test for floating point Not A Number (NAN) value.