OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimQuickbirdRpcModel.cpp
Go to the documentation of this file.
1 //*****************************************************************************
2 // FILE: ossimQuickbirdRpcModel.cpp
3 //
4 // License: See top level LICENSE.txt file.
5 //
6 // DESCRIPTION: Contains declaration of class ossimQuickbirdRpcModel. This
7 // derived class implements the capability of reading Quickbird RPC support
8 // data.
9 //
10 // LIMITATIONS: None.
11 //
12 //*****************************************************************************
13 // $Id: ossimQuickbirdRpcModel.cpp 23564 2015-10-02 14:12:25Z dburken $
14 
17 #include <ossim/base/ossimNotify.h>
30 
31 static const char* RPC00A_TAG = "RPC00A";
32 static const char* RPC00B_TAG = "RPC00B";
33 static const char* ICHIPB_TAG = "ICHIPB";
34 static const char* PIAIMC_TAG = "PIAIMC";
35 static const char* USE00A_TAG = "USE00A";
36 
37 RTTI_DEF1(ossimQuickbirdRpcModel, "ossimQuickbirdRpcModel", ossimRpcModel);
38 
39 
40 //*************************************************************************************************
41 // Constructor
42 //*************************************************************************************************
44  :ossimRpcModel(),
45  theSupportData(new ossimQuickbirdMetaData())
46 {
47 }
48 
49 //*************************************************************************************************
50 // Constructor
51 //*************************************************************************************************
53  : ossimRpcModel(rhs),
54  theSupportData(new ossimQuickbirdMetaData())
55 {
56 }
57 
58 //*************************************************************************************************
61 //*************************************************************************************************
63 : ossimRpcModel(),
64  theSupportData(new ossimQuickbirdMetaData())
65 {
67  if (!handler)
68  return;
69 
70  // Make the gsd nan so it gets computed.
71  theGSD.makeNan();
72 
74 
75  ossimFilename imageFile = handler->getFilename();
76  if (!parseRpcData(imageFile))
77  return;
78 
81  return;
82 }
83 
84 //*************************************************************************************************
85 // Destructor
86 //*************************************************************************************************
88 {
89  theSupportData = 0;
90 }
91 
92 //*************************************************************************************************
93 // Infamous DUP
94 //*************************************************************************************************
96 {
97  return new ossimQuickbirdRpcModel(*this);
98 }
99 
100 //*************************************************************************************************
102 //*************************************************************************************************
104 {
105  bool result = parseNitfFile(file);
106  if ( !result )
107  {
108  result = parseTiffFile(file);
109  }
110  return result;
111 }
112 
113 //*************************************************************************************************
115 //*************************************************************************************************
117 {
118  setErrorStatus();
119 
120  //---
121  // ossimNitfFile::parseFile(...) checks the first eight byte so three calls
122  // to parseFile are not necessary. drb - 21 Dec. 2016
123  //---
124  ossimRefPtr<ossimNitfFile> nitfFilePtr = new ossimNitfFile;
125  if( nitfFilePtr->parseFile( file ) == false )
126  {
127  return false;
128  }
129 
130 #if 0
131  ossimFilename nitfFile = file;
132  ossimRefPtr<ossimNitfFile> nitfFilePtr = new ossimNitfFile;
133  if(!nitfFilePtr->parseFile(nitfFile))
134  {
135  nitfFile = nitfFile.setExtension("NTF");
136  if(!nitfFilePtr->parseFile(nitfFile))
137  {
138  nitfFile = nitfFile.setExtension("ntf");
139  if(!nitfFilePtr->parseFile(nitfFile))
140  return false;
141  }
142  }
143 #endif
144 
146  if (!ih)
147  return false;
148 
150 
151  // Give preference to external RPC data file. Only consider external tiling data if RPC is
152  // provided externally, otherwise expect ICHIPB in NITF:
153  bool useInternalRpcTags = true;
154  if (parseRpcData(file))
155  {
156  useInternalRpcTags = false;
157  if (!parseTileData(file))
158  return false;
159  }
160 
161  // Check for IMD (metadata) file:
162  parseMetaData(file);
163 
164  // Get the gsd.
165  theGSD.line = ossim::nan();
166  theGSD.samp = ossim::nan();
167 
169  tag = ih->getTagData(PIAIMC_TAG);
170  if (tag.valid())
171  {
173  if (p)
174  {
177  }
178  }
179  if (ossim::isnan(theGSD.line))
180  {
181  tag = ih->getTagData(USE00A_TAG);
182  if (tag.valid())
183  {
185  if (p)
186  {
189  }
190  }
191  }
192 
193  // If external RPC data file was correctly parsed, then we can bypass this code block. Otherwise
194  // need to parse internal NITF tags for RPC data:
195  if (useInternalRpcTags)
196  {
197  // Get the the RPC tag:
198  ossimNitfRpcBase* rpcTag = NULL;
199 
200  // Look for the RPC00B tag first.
201  tag = ih->getTagData(RPC00B_TAG);
202  if (tag.valid())
203  rpcTag = PTR_CAST(ossimNitfRpcBase, tag.get());
204 
205  if (!tag.valid())
206  {
207  // Look for RPC00A tag.
208  tag = ih->getTagData(RPC00A_TAG);
209  if (tag.valid())
210  rpcTag = PTR_CAST(ossimNitfRpcBase, tag.get());
211  }
212 
213  if (!rpcTag)
214  return false;
215 
216  // Set the polynomial type.
217  if (rpcTag->getRegisterTagName() == "RPC00B")
218  thePolyType = B;
219  else
220  thePolyType = A;
221 
222  // Parse coefficients:
223  for (ossim_uint32 i=0; i<20; ++i)
224  {
229  }
230 
231  // Initialize other items in tags:
232  theLineScale = rpcTag->getLineScale().toFloat64();
233  theSampScale = rpcTag->getSampleScale().toFloat64();
237  theLineOffset = rpcTag->getLineOffset().toFloat64();
242  theImageID = ih->getImageId();
243  }
244 
247  return true;
248 }
249 
250 //*************************************************************************************************
252 //*************************************************************************************************
254 {
255  setErrorStatus();
256 
257  // Make the gsd nan so it gets computed.
258  theGSD.makeNan();
259 
260  ossimFilename tiffFile = file;
262  if (!tiff->open(file))
263  {
264  return false;
265  }
266 
268 
269  parseMetaData(file);
270 
271  // TIFF format expects the RPC and TILE info to be provided externally:
272  if (!parseRpcData(file))
273  return false;
274 
275  // If no TIL data present, assumes full image:
276  if (!parseTileData(file))
277  return false;
278 
281  return true;
282 }
283 
284 //*************************************************************************************************
287 //*************************************************************************************************
289 {
290  ossimFilename rpcFile (base_name);
291 
292  // There are two possibilities for RPC data files: either each image file has its own RPC data
293  // file, or a single RPC file is provided for a multi-tile scene.
294  rpcFile.setExtension("RPB");
295  if (!findSupportFile(rpcFile))
296  {
297  rpcFile.setExtension("RPA");
298  if (!findSupportFile(rpcFile))
299  return false;
300  }
301 
302  // An RPC file was located, open it:
304  if(!hdr.open(rpcFile))
305  return false;
306 
307  if(hdr.isAPolynomial())
308  thePolyType = A;
309  else
310  thePolyType = B;
311 
312  std::copy(hdr.theLineNumCoeff.begin(), hdr.theLineNumCoeff.end(), theLineNumCoef);
313  std::copy(hdr.theLineDenCoeff.begin(), hdr.theLineDenCoeff.end(), theLineDenCoef);
314  std::copy(hdr.theSampNumCoeff.begin(), hdr.theSampNumCoeff.end(), theSampNumCoef);
315  std::copy(hdr.theSampDenCoeff.begin(), hdr.theSampDenCoeff.end(), theSampDenCoef);
316 
319  theLatScale = hdr.theLatScale;
320  theLonScale = hdr.theLonScale;
327  theImageID = rpcFile.fileNoExtension();
328 
329  return true;
330 }
331 
332 
333 //*************************************************************************************************
335 //*************************************************************************************************
337 {
338 
339  ossimFilename metadataFile (base_name);
340  metadataFile.setExtension("IMD");
341  if (!findSupportFile(metadataFile))
342  return false;
343 
344  if ( !theSupportData.valid() )
346 
347  if(!theSupportData->open(metadataFile))
348  {
349  theSupportData = 0; // ossimRefPtr
350 #if 0 /* This should be wrapped in trace. drb */
352  << "ossimQuickbirdRpcModel::parseMetaData WARNING:"
353  << "\nCould not open IMD file. Sensor ID unknown." << std::endl;
354 #endif
355  return false;
356  }
357 
359  return true;
360 }
361 
362 //*************************************************************************************************
364 //*************************************************************************************************
366 {
367  ossimFilename tileFile (image_file);
368  tileFile.setExtension("TIL");
369 
370  // The TIL file is optional. Consider the image to be the full image if not present:
371  if (!findSupportFile(tileFile))
372  return true;
373 
374  ossimQuickbirdTile tileHdr;
375  if(!tileHdr.open(tileFile))
376  return false;
377 
379  if(!tileHdr.getInfo(info, image_file.file()))
380  return false;
381 
382 // if((info.theUlXOffset != OSSIM_INT_NAN) && (info.theUlYOffset != OSSIM_INT_NAN) &&
383 // (info.theLrXOffset != OSSIM_INT_NAN) && (info.theLrYOffset != OSSIM_INT_NAN) &&
384 // (info.theLlXOffset != OSSIM_INT_NAN) && (info.theLlYOffset != OSSIM_INT_NAN) &&
385 // (info.theUrXOffset != OSSIM_INT_NAN) && (info.theUrYOffset != OSSIM_INT_NAN))
386 // {
387 // theImageClipRect = ossimIrect(ossimIpt(info.theUlXOffset, info.theUlYOffset),
388 // ossimIpt(info.theUrXOffset, info.theUrYOffset),
389 // ossimIpt(info.theLrXOffset, info.theLrYOffset),
390 // ossimIpt(info.theLlXOffset, info.theLlYOffset));
391 // }
392 // else if ((info.theUlXOffset != OSSIM_INT_NAN) && (info.theUlYOffset != OSSIM_INT_NAN) &&
393 // (theImageClipRect.width() != OSSIM_INT_NAN) && (theImageClipRect.height() != OSSIM_INT_NAN))
394 // {
395 // theImageClipRect = ossimIrect(info.theUlXOffset, info.theUlYOffset,
396 // info.theUlXOffset+theImageClipRect.width()-1,
397 // info.theUlYOffset+theImageClipRect.height()-1);
398 // }
399 
400  // Define the RPC model's 2D transform for chipped imagery. Note that the TIL file will only
401  // define an offset, not a full affine. Can only use the tile's UL corner:
402  ossimDpt ul (info.theUlXOffset, info.theUlYOffset);
403  if (!ul.hasNans())
404  setImageOffset(ul);
405  //theImageXform = new ossim2dTo2dShiftTransform(ul);
406 
407  return true;
408 }
409 
410 //*************************************************************************************************
412 //*************************************************************************************************
414 {
422 
423  //---
424  // NOTE: We must call "updateModel()" to set parameter used by base
425  // ossimRpcModel prior to calling lineSampleHeightToWorld or all
426  // the world points will be same.
427  //---
428  updateModel();
429 
430  ossimGpt v0, v1, v2, v3;
435 
437 
438  // Set the ground reference point using the model.
440 
441  if( theGSD.hasNans() )
442  {
443  try
444  {
445  // This will set theGSD and theMeanGSD. Method throws ossimException.
446  computeGsd();
447  }
448  catch (const ossimException& e)
449  {
451  << "ossimQuickbirdRpcModel::finishConstruction -- caught exception:\n"
452  << e.what() << std::endl;
453  }
454  }
455 }
456 
458  const char* prefix) const
459 {
460  // sanity check only. This shoulc always be true
461  if(theSupportData.valid())
462  {
463  ossimString supportPrefix = ossimString(prefix) + "support_data.";
464  theSupportData->saveState(kwl, supportPrefix);
465  }
466 
467  return ossimRpcModel::saveState(kwl, prefix);
468 }
469 
471  const char* prefix)
472 {
473  // sanity check only. This shoulc always be true
474  if(theSupportData.valid())
475  {
476  ossimString supportPrefix = ossimString(prefix) + "support_data.";
477  theSupportData->loadState(kwl, supportPrefix);
478  }
479  return ossimRpcModel::loadState(kwl, prefix);
480 }
481 
482 //*************************************************************************************************
483 // Given an initial filename with case-agnostic extension, this method searches first for an
484 // image-specific instance of that file (i.e., with R*C* in the filename) before considering
485 // the mosaic-global support file (R*C* removed). If a file is found, the argument is modified to
486 // match the actual filename and TRUE is returned. Otherwise, argument filename is left unchanged
487 // and FALSE is returned.
488 //*************************************************************************************************
490 {
491  ossimFilename f (filename);
492  ossimString extension = f.ext();
493  if(f.exists())
494  {
495  filename = f;
496  return true;
497  }
498  // Search for support file with same basename as image:
499  extension.upcase();
500  f.setExtension(extension);
501  if(f.exists())
502  {
503  filename = f;
504  return true;
505  }
506  extension.downcase();
507  if(f.exists())
508  {
509  filename = f;
510  return true;
511  }
512 
513  // None found so far, search for mosaic-global support file:
514  f = f.replaceAllThatMatch("_R[0-9]+C[0-9]+");
515  if(f.exists())
516  {
517  filename = f;
518  return true;
519  }
520  extension.upcase();
521  f.setExtension(extension);
522  if(f.exists())
523  {
524  filename = f;
525  return true;
526  }
527 
528 
529  // Modify argument to match good filename:
530  return false;
531 }
double theSampOffset
ossimString theSensorID
PolynomialType thePolyType
ossimString getLineScale() const
double theSampNumCoef[20]
bool parseTileData(const ossimFilename &file)
Reads the TIL file for pertinent info. Returns TRUE if successful.
ossimRefPtr< ossimQuickbirdMetaData > theSupportData
RTTI_DEF1(ossimQuickbirdRpcModel, "ossimQuickbirdRpcModel", ossimRpcModel)
void finishConstruction()
Collects common code among all parsers.
bool parseMetaData(const ossimFilename &file)
Initializes the support data member with metadata file info. Returns TRUE if successful.
static ossimString upcase(const ossimString &aString)
Definition: ossimString.cpp:34
ossimString getGeodeticHeightScale() const
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to the load (recreate) the state of the object from a keyword list.
ossim_float64 width() const
Definition: ossimDrect.h:522
ossimNitfImageHeader * getNewImageHeader(ossim_uint32 imageNumber) const
ossimString getLineDenominatorCoeff(ossim_uint32 idx) const
bool open(const ossimFilename tileFile)
Represents serializable keyword/value map.
bool valid() const
Definition: ossimRefPtr.h:75
ossimString theImageID
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
const ossimDpt & ul() const
Definition: ossimDrect.h:339
double y
Definition: ossimDpt.h:165
ossimString getSampleOffset() const
virtual ossimIrect getImageRectangle(ossim_uint32 resLevel=0) const
Returns overall bounding rect in image space.
virtual void updateModel()
ossim_float64 hgt
Height in meters above the ellipsiod.
Definition: ossimGpt.h:274
bool open(const ossimFilename &file)
double theLonScale
double theLineScale
ossimString getSampleDenominatorCoeff(ossim_uint32 idx) const
double theSampDenCoef[20]
ossimString getLineOffset() const
double theLineNumCoef[20]
double theLatOffset
bool parseRpcData(const ossimFilename &file)
Given some base name for the image data, parses the associated RPC data file.
double theHgtOffset
double theLonOffset
ossimString replaceAllThatMatch(const char *regularExpressionPattern, const char *value="") const
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
bool findSupportFile(ossimFilename &file) const
Given an initial filename with case-agnostic extension, this method searches first for an image-speci...
bool getInfo(ossimQuickbirdTileInfo &result, const ossimFilename &filename) const
bool exists() const
ossim_float64 lon
Definition: ossimGpt.h:266
virtual const ossimFilename & getFilename() const
Returns the filename.
bool parseNitfFile(const ossimFilename &file)
Parses a NITF image file for RPC info. Returns TRUE if successful.
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.
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Method to save the state of the object to a keyword list.
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
saveState Fulfills ossimObject base-class pure virtuals.
std::vector< double > theSampNumCoeff
unsigned int ossim_uint32
bool parseTiffFile(const ossimFilename &file)
Parses a tagged TIFF image file for RPC info. Returns TRUE if successful.
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
std::vector< double > theLineNumCoeff
virtual ossimObject * dup() const
dup() Returns pointer to a new instance, copy of this.
static ossimString downcase(const ossimString &aString)
Definition: ossimString.cpp:48
virtual ossimIrect getImageRectangle(ossim_uint32 resLevel=0) const
Returns zero-based bounding rectangle of the image.
void setImageOffset(const ossimDpt &offset_to_chip_ul)
Allows setting an offset to a subimage while using the coefficients of a full-image model...
bool hasNans() const
Definition: ossimDpt.h:67
ossim_float64 height() const
Definition: ossimDrect.h:517
std::vector< double > theSampDenCoeff
ossimString getLineNumeratorCoeff(ossim_uint32 idx) const
ossimDrect theImageClipRect
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
loadState Fulfills ossimObject base-class pure virtuals.
ossim_int32 samp
Definition: ossimIpt.h:141
ossimString getSampleNumeratorCoeff(ossim_uint32 idx) const
ossimDpt midPoint() const
Definition: ossimDrect.h:817
ossimString getGeodeticLatScale() const
const ossimDpt & ur() const
Definition: ossimDrect.h:340
ossimFilename fileNoExtension() const
virtual bool open(const ossimFilename &image_file)
Returns true if the image_file can be opened and is a valid tiff file.
double x
Definition: ossimDpt.h:164
Image handler used for tiled Quickbird imagery.
bool open(const ossimFilename &imageFile)
Open method that takes the image file, derives the metadata, header and rpc files, then calls parse methods parseMetaData, parseHdrData, and parseRpcData.
ossimRefPtr< ossimNitfRegisteredTag > getTagData(const ossimString &tagName)
double theSampScale
ossimFilename file() const
ossim_int32 line
Definition: ossimIpt.h:142
ossimString ext() const
ossimString getGeodeticLonOffset() const
bool parseFile(const ossimFilename &file)
ossim_float64 getMeanGsdInMeters() const
const ossimDpt & ll() const
Definition: ossimDrect.h:342
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
ossimFilename & setExtension(const ossimString &e)
Sets the extension of a file name.
double theLineOffset
const ossimDpt & lr() const
Definition: ossimDrect.h:341
double theHgtScale
ossimString getGeodeticLonScale() const
ossim_float64 getMeanGsdInMeters() const
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
void makeNan()
Definition: ossimDpt.h:65
std::vector< double > theLineDenCoeff
virtual bool parseFile(const ossimFilename &file)
Public method for parsing generic image file.
bool isnan(const float &v)
isnan Test for floating point Not A Number (NAN) value.
Definition: ossimCommon.h:91