//*************************************************************************************************
//! Parses a tagged TIFF image file for RPC info. Returns TRUE if successful.
//*************************************************************************************************
bool rspfQuickbirdRpcModel::parseTiffFile(const rspfFilename& file)
{
   setErrorStatus();

   // Make the gsd nan so it gets computed.
   theGSD.makeNan();

   rspfFilename tiffFile = file;
   rspfRefPtr<rspfTiffTileSource> tiff = new rspfTiffTileSource();
   if (!tiff->open(file))
   {
      return false;
   }

   theImageClipRect = tiff->getImageRectangle();

   parseMetaData(file);

   if (!parseRpcData(file))
      return false;

   if (!parseTileData(file))
      return false;

   finishConstruction();
   clearErrorStatus();
   return true;
}
//*************************************************************************************************
//! Constructor for multiple tile-files sharing common RPC model initializes given pointer
//! to multi-tile-files handler.
//*************************************************************************************************
rspfQuickbirdRpcModel::rspfQuickbirdRpcModel(const rspfQbTileFilesHandler* handler)
:  rspfRpcModel(),
   theSupportData(new rspfQuickbirdMetaData())
{
   setErrorStatus();
   if (!handler)
      return;


   // Make the gsd nan so it gets computed.
   theGSD.makeNan();

   theImageClipRect = handler->getImageRectangle();

   rspfFilename imageFile = handler->getFilename();
   if (!parseRpcData(imageFile))
      return;

   //loong
   if(!theSupportData->open(imageFile))
	   return;

   finishConstruction();
   clearErrorStatus();
   return;
}
//*************************************************************************************************
//! Constructor for multiple tile-files sharing common RPC model initializes given pointer
//! to multi-tile-files handler.
//*************************************************************************************************
ossimQuickbirdRpcModel::ossimQuickbirdRpcModel(const ossimQbTileFilesHandler* handler)
:  ossimRpcModel(),
   theSupportData(0)
{
   setErrorStatus();
   if (!handler)
      return;

   // Make the gsd nan so it gets computed.
   theGSD.makeNan();

   theImageClipRect = handler->getImageRectangle();

   ossimFilename imageFile = handler->getFilename();
   if (!parseRpcData(imageFile))
      return;

   finishConstruction();
   clearErrorStatus();
   return;
}
//*****************************************************************************
//  CONSTRUCTOR: ossimIkonosRpcModel
//  
//  Constructs given filenames for metadata and RPC data.
//  
//*****************************************************************************
ossimIkonosRpcModel::ossimIkonosRpcModel(const ossimFilename& metadata,
                                         const ossimFilename& rpcdata)
   :
   ossimRpcModel(),
   theSupportData(0)
{
   if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimIkonosRpcModel Constructor #2: entering..." << std::endl;

   theSupportData = new ossimIkonosMetaData();

   parseMetaData(metadata);
   parseRpcData (rpcdata);
   finishConstruction();

   //***
   // Save current state in RPC model format:
   //***
   ossimString drivePart;
   ossimString pathPart;
   ossimString filePart;
   ossimString extPart;
   metadata.split(drivePart,
                  pathPart,
                  filePart,
                  extPart);
   
   ossimFilename init_rpc_geom;
   init_rpc_geom.merge(drivePart,
                       pathPart,
                       INIT_RPC_GEOM_FILENAME,
                       "");
//      (metadata.path().dirCat(ossimRpcModel::INIT_RPC_GEOM_FILENAME));
   ossimKeywordlist kwl (init_rpc_geom);
   saveState(kwl);
   
   if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimIkonosRpcModel Constructor #2: returning..." << std::endl;
}
//*************************************************************************************************
//! Parses a NITF image file for RPC info. Returns TRUE if successful.
//*************************************************************************************************
bool rspfQuickbirdRpcModel::parseNitfFile(const rspfFilename& file)
{
   setErrorStatus();
   rspfFilename nitfFile = file;
   
   rspfRefPtr<rspfNitfFile> nitfFilePtr = new rspfNitfFile;
   
   if(!nitfFilePtr->parseFile(nitfFile))
   {
      nitfFile = nitfFile.setExtension("NTF");
      if(!nitfFilePtr->parseFile(nitfFile))
      {
         nitfFile = nitfFile.setExtension("ntf");
         if(!nitfFilePtr->parseFile(nitfFile))
            return false;
      }
   }
   
   rspfRefPtr<rspfNitfImageHeader> ih = nitfFilePtr->getNewImageHeader(0);
   if (!ih)
      return false;

   theImageClipRect = ih->getImageRect();
 
   // Give preference to external RPC data file:
   bool useInternalRpcTags = false;
   if(!parseRpcData(file))
      useInternalRpcTags = true;
   
   if (!parseTileData(file))
      return false;
  
   // Check for IMD (metadata) file:
   parseMetaData(file);

   // Get the gsd.
   theGSD.line = rspf::nan();
   theGSD.samp = rspf::nan();
   
   rspfRefPtr<rspfNitfRegisteredTag> tag;
   tag = ih->getTagData(PIAIMC_TAG);
   if (tag.valid())
   {
      rspfNitfPiaimcTag* p = PTR_CAST(rspfNitfPiaimcTag, tag.get());
      if (p)
      {
         theGSD.line = p->getMeanGsdInMeters();
         theGSD.samp = theGSD.line;
      }
   }
   if (rspf::isnan(theGSD.line))
   {
      tag = ih->getTagData(USE00A_TAG);
      if (tag.valid())
      {
         rspfNitfUse00aTag* p = PTR_CAST(rspfNitfUse00aTag, tag.get());
         if (p)
         {
            theGSD.line = p->getMeanGsdInMeters();
            theGSD.samp = theGSD.line;
         }
      }
   }

   // If external RPC data file was correctly parsed, then we can bypass this code block. Otherwise
   // need to parse internal NITF tags for RPC data:
   if (useInternalRpcTags)
   {
      // Get the the RPC tag:
      rspfNitfRpcBase* rpcTag = NULL;
      
      // Look for the RPC00B tag first.
      tag = ih->getTagData(RPC00B_TAG);
      if (tag.valid())
         rpcTag = PTR_CAST(rspfNitfRpcBase, tag.get());
      
      if (!tag.valid())
      {
         // Look for RPC00A tag.
         tag = ih->getTagData(RPC00A_TAG);
         if (tag.valid())
            rpcTag = PTR_CAST(rspfNitfRpcBase, tag.get());
      }
      
      if (!rpcTag)
         return false;
      
      // Set the polynomial type.
      if (rpcTag->getRegisterTagName() == "RPC00B")
         thePolyType = B;
      else
         thePolyType = A;

      // Parse coefficients:
      for (rspf_uint32 i=0; i<20; ++i)
      {
         theLineNumCoef[i] = rpcTag->getLineNumeratorCoeff(i).toFloat64();
         theLineDenCoef[i] = rpcTag->getLineDenominatorCoeff(i).toFloat64();
         theSampNumCoef[i] = rpcTag->getSampleNumeratorCoeff(i).toFloat64();
         theSampDenCoef[i] = rpcTag->getSampleDenominatorCoeff(i).toFloat64();
      }

      // Initialize other items in tags:
      theLineScale  = rpcTag->getLineScale().toFloat64();
      theSampScale  = rpcTag->getSampleScale().toFloat64();
      theLatScale   = rpcTag->getGeodeticLatScale().toFloat64();
      theLonScale   = rpcTag->getGeodeticLonScale().toFloat64();
      theHgtScale   = rpcTag->getGeodeticHeightScale().toFloat64();
      theLineOffset = rpcTag->getLineOffset().toFloat64();
      theSampOffset = rpcTag->getSampleOffset().toFloat64();
      theLatOffset  = rpcTag->getGeodeticLatOffset().toFloat64();
      theLonOffset  = rpcTag->getGeodeticLonOffset().toFloat64();
      theHgtOffset  = rpcTag->getGeodeticHeightOffset().toFloat64();
      theImageID    = ih->getImageId();
   }

   finishConstruction();
   clearErrorStatus();
   return true;
}
bool ossimIkonosRpcModel::parseTiffFile(const ossimFilename& filename)
{
   bool result = false;
   
   ossimRefPtr<ossimTiffTileSource> tiff = new ossimTiffTileSource();

   if ( tiff->open(filename) )
   {
      if ( !theSupportData )
      {
         theSupportData = new ossimIkonosMetaData();
      }

      if ( theSupportData->open(filename) == false )
      {
         if(traceDebug())
         {
            // Currently not required by model so we will not error out here.
            ossimNotify(ossimNotifyLevel_DEBUG)
               << "WARNING: ossimIkonosMetaData::open returned false.\n"
               << std::endl;
         }
      }
      else
      {
         // copy ossimIkonosMetada-sensor into ossimIkonosRpcModel-sensorId
         theSensorID = theSupportData->getSensorID();
      }

      //convert file to rpc filename and hdr filename so we can get some info
      ossimFilename rpcfile = filename.noExtension();
      rpcfile += "_rpc.txt";
      
      ossimFilename hdrfile = filename;
      hdrfile.setExtension(ossimString("hdr"));
      
      if( parseHdrData(hdrfile) )
      {
         // parseRpcData sets the error status on error.
         parseRpcData (rpcfile);
         if ( !getErrorStatus() ) //check for errors in parsing rpc data
         {
            finishConstruction();
            
            //---
            // Save current state in RPC model format:
            //---
            ossimString drivePart;
            ossimString pathPart;
            ossimString filePart;
            ossimString extPart;
            filename.split(drivePart,
                           pathPart,
                           filePart,
                           extPart);
            
            ossimFilename init_rpc_geom;
            init_rpc_geom.merge(drivePart,
                                pathPart,
                                INIT_RPC_GEOM_FILENAME,
                                "");

            ossimKeywordlist kwl (init_rpc_geom);
            saveState(kwl);

            // If we get here set the return status to true.
            result = true;

         } // matches: if ( !getErrorStatus() )
   
      } // matches: if( parseHdrData(hdrfile) )

   } // matches:  if ( tiff->open(filename) )
   
   if ( traceExec() )
   {
      ossimNotify(ossimNotifyLevel_DEBUG)
         << "return status: " << (result?"true\n":"false\n")
         << "DEBUG ossimIkonosRpcModel parseTiffFile: returning..."
         << std::endl;
   }

   return result;
}
//*****************************************************************************
//  CONSTRUCTOR: ossimIkonosRpcModel
//  
//  Constructs given a geometry file that specifies the filenames for the
//  metadata and RPC data files.
//  
//*****************************************************************************
ossimIkonosRpcModel::ossimIkonosRpcModel(const ossimFilename& geom_file)
   :  ossimRpcModel(),
      theSupportData(0)
{
   if (traceExec())
   {
      ossimNotify(ossimNotifyLevel_DEBUG)
         << "DEBUG ossimIkonosRpcModel Constructor #1: entering..."
         << std::endl;
   }

   theSupportData = new ossimIkonosMetaData();
   
   ossimKeywordlist kwl(geom_file);
   const char* value;
   
   //***
   // Assure this keywordlist contains correct type info:
   //***
   value = kwl.find(ossimKeywordNames::TYPE_KW);
   if (!value || (strcmp(value, "ossimIkonosRpcModel")))
   {
      if (traceDebug())
      {
         ossimNotify(ossimNotifyLevel_DEBUG)
            << "DEBUG  ossimIkonosRpcModel Constructor #1:"
            << "\nFailed attempt to construct. sensor type \""<<value
            << "\" does not match \"ossimIkonosRpcModel\"." << std::endl;
      }

      theErrorStatus++;
      if (traceExec())
      {
         ossimNotify(ossimNotifyLevel_DEBUG)
            << "DEBUG  ossimIkonosRpcModel Constructor #1: returning..."
            << std::endl;
      }
      return;
   }

   //***
   // Read meta data filename from geom file:
   //***
   value = kwl.find(META_DATA_FILE);
   if (!value)
   {
      theErrorStatus++;
      if (traceExec())
      {
         ossimNotify(ossimNotifyLevel_DEBUG)
            << "DEBUG ossimIkonosRpcModel Constructor #1: returning..."
            << std::endl;
      }
      return;
   }

   ossimFilename metadata (value);

   //***
   // Read RPC data filename from geom file:
   //***
   value = kwl.find(RPC_DATA_FILE);
   if (!value)
   {
      theErrorStatus++;
      if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG  ossimIkonosRpcModel Constructor #1: returning..." << std::endl;
      return;
   }
   ossimFilename rpcdata (value);

   parseMetaData(metadata);
   parseRpcData (rpcdata);
   finishConstruction();

   ossimString drivePart;
   ossimString pathPart;
   ossimString filePart;
   ossimString extPart;
   geom_file.split(drivePart,
                   pathPart,
                   filePart,
                   extPart);

   

   if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG returning..." << std::endl;
   
   return;
}