OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimNitfRpcModel.cpp
Go to the documentation of this file.
1 //*****************************************************************************
2 // FILE: ossimNitfRpcModel.cc
3 //
4 // License: LGPL
5 //
6 // See LICENSE.txt file in the top level directory for more details.
7 //
8 // AUTHOR: Oscar Kramer
9 //
10 // DESCRIPTION: Contains implementation of class ossimNitfRpcModel. This
11 // derived class implements the capability of reading Nitf RPC support
12 // data.
13 //
14 // LIMITATIONS: None.
15 //
16 //*****************************************************************************
17 // $Id: ossimNitfRpcModel.cpp 16643 2010-02-22 21:32:43Z dburken $
18 
20 
21 RTTI_DEF1(ossimNitfRpcModel, "ossimNitfRpcModel", ossimRpcModel);
22 
33 
34 //***
35 // Define Trace flags for use within this file:
36 //***
37 #include <ossim/base/ossimTrace.h>
38 static ossimTrace traceExec ("ossimNitfRpcModel:exec");
39 static ossimTrace traceDebug ("ossimNitfRpcModel:debug");
40 
41 static const char* RPC00A_TAG = "RPC00A";
42 static const char* RPC00B_TAG = "RPC00B";
43 static const char* PIAIMC_TAG = "PIAIMC";
44 static const char* STDIDC_TAG = "STDIDC";
45 static const char* USE00A_TAG = "USE00A";
46 
48  :
49  ossimRpcModel(),
50  theDecimation(1.0)
51 {
52 }
53 
55  :
56  ossimRpcModel(rhs),
57  theDecimation(1.0)
58 {
59 }
60 
61 //*****************************************************************************
62 // CONSTRUCTOR: ossimNitfRpcModel
63 //
64 // Constructs given filename for NITF file
65 //
66 //*****************************************************************************
68  :
69  ossimRpcModel(),
70  theDecimation(1.0)
71 {
72  if (traceExec())
73  {
75  << "DEBUG ossimNitfRpcModel::ossimNitfRpcModel(nitfFile): entering..."
76  << std::endl;
77  }
78  if(!parseFile(nitfFile))
79  {
80  if (traceExec())
81  {
83  << "DEBUG ossimNitfRpcModel::ossimNitfRpcModel(nitfFile): Unable to parse file " << nitfFile
84  << std::endl;
85  }
87  }
88 
89  if (traceExec())
90  {
92  << "DEBUG ossimNitfRpcModel::ossimNitfRpcModel(nitfFile): returning..."
93  << std::endl;
94  }
95 }
96 
98 {
99  return new ossimNitfRpcModel(*this);
100 }
101 
103  ossim_uint32 entryIndex)
104 {
106 
107  if(!file->parseFile(nitfFile))
108  {
109  setErrorStatus();
110  return false;
111  }
112 
114  if(!ih)
115  {
116  setErrorStatus();
117  return false;
118  }
119 
120  return parseImageHeader(ih.get());
121 
122 }
123 
125 {
126  // Do this first so we don't waste time if not rpc image.
127  if (getRpcData(ih) == false)
128  {
129  if (traceDebug())
130  {
132  << "ossimNitfRpcModel::parseFile DEBUG:"
133  << "\nError parsing rpc tags. Aborting with error."
134  << std::endl;
135  }
136  setErrorStatus();
137  return false;
138  }
139 
140 
141  //---
142  // Get the decimation if any from the header "IMAG" field.
143  //
144  // Look for string like:
145  // "/2" = 1/2
146  // "/4 = 1/4
147  // ...
148  // "/16 = 1/16
149  // If it is full resolution it should be "1.0"
150  //---
152  if ( os.contains("/") )
153  {
154  os = os.after("/");
155  ossim_float64 d = os.toFloat64();
156  if (d)
157  {
158  theDecimation = 1.0 / d;
159  }
160  }
161 
162  //***
163  // Fetch Image ID:
164  //***
165  theImageID = ih->getImageId();
166 
167  ossimIrect imageRect = ih->getImageRect();
168 
169  //---
170  // Fetch Image Size:
171  //---
173  static_cast<ossim_int32>(imageRect.height() / theDecimation);
175  static_cast<ossim_int32>(imageRect.width() / theDecimation);
176 
177  // Search for the STDID Tag to fetch mission (satellite) name:
178  getSensorID(ih);
179 
180  //***
181  // Assign other data members:
182  //***
188 
189  //***
190  // Assign the bounding image space rectangle:
191  //***
192  theImageClipRect = ossimDrect(0.0, 0.0,
194 
195  //---
196  // Assign the bounding ground polygon:
197  //
198  // NOTE: We will use the base ossimRpcModel for transformation since all
199  // of our calls are in full image space (not decimated).
200  //---
201  ossimGpt v0, v1, v2, v3;
202  ossimDpt ip0 (0.0, 0.0);
204  ossimDpt ip1 (theImageSize.samp-1.0, 0.0);
206  ossimDpt ip2 (theImageSize.samp-1.0, theImageSize.line-1.0);
208  ossimDpt ip3 (0.0, theImageSize.line-1.0);
210 
212  = ossimPolygon (ossimDpt(v0), ossimDpt(v1), ossimDpt(v2), ossimDpt(v3));
213 
214  updateModel();
215 
216  // Set the ground reference point.
218  theHgtOffset,
219  theRefGndPt);
221  {
222  if (traceDebug())
223  {
225  << "ossimNitfRpcModel::ossimNitfRpcModel DEBUG:"
226  << "\nGround Reference Point not valid."
227  << " Aborting with error..."
228  << std::endl;
229  }
230  setErrorStatus();
231  return false;
232  }
233 
234  //---
235  // This will set theGSD and theMeanGSD. This model doesn't need these but
236  // others do.
237  //---
238  try
239  {
240  computeGsd();
241  }
242  catch (const ossimException& e)
243  {
244  if (traceDebug())
245  {
247  << "ossimNitfRpcModel::ossimNitfRpcModel DEBUG:\n"
248  << e.what() << std::endl;
249  }
250  }
251 
252  if (traceExec())
253  {
255  << "DEBUG ossimNitfRpcModel::parseFile: returning..."
256  << std::endl;
257  }
258 
259  return true;
260 }
261 
263  ossimDpt& image_point) const
264 {
265  // Get the full res (not decimated) point.
266  ossimRpcModel::worldToLineSample(world_point, image_point);
267 
268  // Apply decimation.
269  image_point.x = image_point.x * theDecimation;
270  image_point.y = image_point.y * theDecimation;
271 }
272 
274  const ossimDpt& image_point,
275  const double& heightEllipsoid,
276  ossimGpt& worldPoint) const
277 {
278  // Convert image point to full res (not decimated) point.
279  ossimDpt pt;
280  pt.x = image_point.x / theDecimation;
281  pt.y = image_point.y / theDecimation;
282 
283  // Call base...
284  ossimRpcModel::lineSampleHeightToWorld(pt, heightEllipsoid, worldPoint);
285 }
286 
288  const char* prefix) const
289 {
290  // Save the decimation.
291  kwl.add(prefix, "decimation", theDecimation);
292 
293  // Call base.
294  return ossimRpcModel::saveState(kwl, prefix);
295 }
296 
298  const char* prefix)
299 {
300  // Lookup decimation.
301  const char* value = kwl.find(prefix, "decimation");
302  if (value)
303  {
305  if (theDecimation <= 0.0)
306  {
307  // Do not allow negative or "0.0"(divide by zero).
308  theDecimation = 1.0;
309  }
310  }
311 
312  // Call base.
313  return ossimRpcModel::loadState(kwl, prefix);
314 }
315 
317 {
318  theGSD.line = ossim::nan();
319  theGSD.samp = ossim::nan();
320 
321  if (!ih)
322  {
323  return;
324  }
325 
327  tag = ih->getTagData(PIAIMC_TAG);
328  if (tag.valid())
329  {
331  if (p)
332  {
335  return;
336  }
337  }
338 
339  tag = ih->getTagData(USE00A_TAG);
340  if (tag.valid())
341  {
343  if (p)
344  {
347  }
348  }
349 }
350 
352 {
353  theSensorID = "UNKNOWN";
354 
355  if (!ih)
356  {
357  return;
358  }
359 
361  tag = ih->getTagData(STDIDC_TAG);
362  if (tag.valid())
363  {
365  if (p)
366  {
367  theSensorID = p->getMission();
368  return;
369  }
370  }
371 
372  if (traceDebug())
373  {
375  << "ossimNitfRpcModel::getSensorID DEBUG:"
376  << "\ntheSensorID set to: " << theSensorID << endl;
377  }
378 }
379 
381 {
382  if (!ih)
383  {
384  return false;
385  }
386 
387  // Get the the RPC tag:
388  ossimNitfRpcBase* rpcTag = 0;
389 
390  // Look for the RPC00B tag first.
391  ossimRefPtr<ossimNitfRegisteredTag> tag = ih->getTagData(RPC00B_TAG);
392  if (tag.valid())
393  {
394  rpcTag = PTR_CAST(ossimNitfRpcBase, tag.get());
395  }
396 
397  if (!rpcTag)
398  {
399  // Look for RPC00A tag.
400  tag = ih->getTagData(RPC00A_TAG);
401  if (tag.valid())
402  {
403  rpcTag = PTR_CAST(ossimNitfRpcBase, tag.get());
404  }
405  }
406 
407  if (!rpcTag)
408  {
409  if (traceDebug())
410  {
412  << "ossimNitfRpcModel::getRpcData DEBUG:"
413  << "\nCould not find neither RPC tags <" << RPC00A_TAG
414  << "> nor <" << RPC00B_TAG
415  << "\nAborting with error..."
416  << std::endl;
417  }
418  return false;
419  }
420 
421  if ( rpcTag->getSuccess() == false )
422  {
423  if (traceDebug())
424  {
426  << "ossimNitfRpcModel::getRpcData DEBUG:"
427  << "\nSuccess flag set to false."
428  << "\nAborting with error..."
429  << std::endl;
430  }
431  return false;
432  }
433 
434  // Set the polynomial type.
435  if (rpcTag->getRegisterTagName() == "RPC00B")
436  {
437  thePolyType = B;
438  }
439  else
440  {
441  thePolyType = A;
442  }
443 
444  // Now parse the tag block for pertinent data:
445  theBiasError = rpcTag->getErrorBias().toFloat64();
446  theRandError = rpcTag->getErrorRand().toFloat64();
447  theLineOffset = rpcTag->getLineOffset().toFloat64();
452  theLineScale = rpcTag->getLineScale().toFloat64();
453  theSampScale = rpcTag->getSampleScale().toFloat64();
457 
458  // OBC has some data with negative height offsets that blows up the ray intersection with elevation model. The bilinear model seems more accurate than trying to work around this.
459  if (ih->getImageSource().trim() == "OBC" && theHgtOffset < 0)
460  {
461  if (traceDebug())
462  {
464  << "ossimNitfRpcModel::getRpcData DEBUG:"
465  << "\nHeight Offset will force invalid ellipsoid intersection."
466  << "\nAborting with error..."
467  << std::endl;
468  }
469  return false;
470  }
471 
472  // Parse coefficients:
473  ossim_uint32 i;
474 
475  for (i=0; i<20; ++i)
476  {
481  }
482 
483  // Assign other data members to default values:
485  theRandError*theRandError); // meters
486 
487  return true;
488 }
double theSampOffset
ossimString theSensorID
PolynomialType thePolyType
ossimString getLineScale() const
virtual void worldToLineSample(const ossimGpt &world_point, ossimDpt &image_point) const
worldToLineSample() Overrides base class implementation.
double theSampNumCoef[20]
ossimString getMission() const
ossimString getGeodeticHeightScale() const
ossimNitfImageHeader * getNewImageHeader(ossim_uint32 imageNumber) const
ossimString getLineDenominatorCoeff(ossim_uint32 idx) const
Represents serializable keyword/value map.
bool isLonNan() const
Definition: ossimGpt.h:140
bool valid() const
Definition: ossimRefPtr.h:75
const char * find(const char *key) const
ossimString theImageID
bool getSuccess() const
double samp
Definition: ossimDpt.h:164
virtual std::string getRegisterTagName() const
This will return the name of the registered tag for this user defined header.
double nan()
Method to return ieee floating point double precision NAN.
Definition: ossimCommon.h:135
double y
Definition: ossimDpt.h:165
ossim_uint32 height() const
Definition: ossimIrect.h:487
bool contains(char aChar) const
Definition: ossimString.h:58
virtual bool parseImageHeader(const ossimNitfImageHeader *ih)
virtual ossimString getImageSource() const =0
ossimString getSampleOffset() const
void getSensorID(const ossimNitfImageHeader *ih)
Attempts to get sensor ID from nitf tags and initialize ossimSensorModel::theSensorID.
virtual ossimString getImageMagnification() const =0
virtual void updateModel()
ossim_float64 hgt
Height in meters above the ellipsiod.
Definition: ossimGpt.h:274
double theLonScale
bool isLatNan() const
Definition: ossimGpt.h:139
double theLineScale
ossimString getSampleDenominatorCoeff(ossim_uint32 idx) const
double theSampDenCoef[20]
ossimString getLineOffset() const
double theLineNumCoef[20]
double theLatOffset
double ossim_float64
void add(const char *prefix, const ossimKeywordlist &kwl, bool overwrite=true)
double theHgtOffset
double theLonOffset
void computeGsd()
This method computes the ground sample distance(gsd) and sets class attributes theGSD and theMeanGSD ...
double line
Definition: ossimDpt.h:165
ossimString getGeodeticHeightOffset() const
double theRandError
virtual bool parseFile(const ossimFilename &nitfFile, ossim_uint32 entryIndex=0)
Method to parse an nitf file and initialize model.
ossim_float64 lon
Definition: ossimGpt.h:266
ossim_float64 theNominalPosError
double theLatScale
virtual const char * what() const
Returns the error message.
virtual ossimIrect getImageRect() const =0
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
saveState Fulfills ossimObject base-class pure virtuals.
RTTI_DEF1(ossimNitfRpcModel, "ossimNitfRpcModel", ossimRpcModel)
unsigned int ossim_uint32
ossimString trim(const ossimString &valueToTrim=ossimString(" \\)) const
this will strip lead and trailing character passed in.
ossimPolygon theBoundGndPolygon
virtual ossimString getImageId() const =0
ossim_float64 toFloat64() const
#define PTR_CAST(T, p)
Definition: ossimRtti.h:321
virtual void lineSampleHeightToWorld(const ossimDpt &image_point, const double &heightEllipsoid, ossimGpt &worldPoint) const
ossim_uint32 width() const
Definition: ossimIrect.h:500
ossimString getErrorBias() const
ossimString getLineNumeratorCoeff(ossim_uint32 idx) const
bool getRpcData(const ossimNitfImageHeader *ih)
Get model information from either the RPC00A or RPC00B tag.
ossimDrect theImageClipRect
ossim_int32 samp
Definition: ossimIpt.h:141
ossimString getSampleNumeratorCoeff(ossim_uint32 idx) const
void getGsd(const ossimNitfImageHeader *ih)
Attempts to get gsd from nitf tags and initialize ossimSensorModel::theGsd.
virtual ossimObject * dup() const
dup() Returns pointer to a new instance, copy of this.
ossimString getGeodeticLatScale() const
double x
Definition: ossimDpt.h:164
ossimRefPtr< ossimNitfRegisteredTag > getTagData(const ossimString &tagName)
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Saves "decimation".
ossimString getErrorRand() const
double theSampScale
ossim_int32 line
Definition: ossimIpt.h:142
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Looks for decimation.
ossimString getGeodeticLonOffset() const
bool parseFile(const ossimFilename &file)
ossim_float64 getMeanGsdInMeters() const
ossim_float64 lat
Definition: ossimGpt.h:265
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
loadState Fulfills ossimObject base-class pure virtuals.
ossimString getSampleScale() const
double theLineDenCoef[20]
ossimString getGeodeticLatOffset() const
double theLineOffset
ossimString after(const ossimString &str, std::string::size_type pos=0) const
METHOD: after(str, pos) Returns string immediately after the token str.
virtual void lineSampleHeightToWorld(const ossimDpt &image_point, const double &heightEllipsoid, ossimGpt &worldPoint) const
lineSampleHeightToWorld() Backs out decimation of image_point (if needed) then calls: ossimRpcModel::...
double theHgtScale
double theBiasError
error
virtual void worldToLineSample(const ossimGpt &world_point, ossimDpt &image_point) const
worldToLineSample() Calls ossimRpcModel::worldToLineSample(), then applies (if needed) decimation...
ossimString getGeodeticLonScale() const
ossim_float64 getMeanGsdInMeters() const
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
ossim_float64 theDecimation
Stored from header field "IMAG".
int ossim_int32