diff --git a/Modules/Adapters/OSSIMAdapters/include/otbDEMHandler.h b/Modules/Adapters/OSSIMAdapters/include/otbDEMHandler.h index 528144e916d3c06135cdb501bd37487718c5042d..7e51a0c79178a1e1e0489cd45eb0c797e6311343 100644 --- a/Modules/Adapters/OSSIMAdapters/include/otbDEMHandler.h +++ b/Modules/Adapters/OSSIMAdapters/include/otbDEMHandler.h @@ -107,9 +107,29 @@ public: /** return true if the directoty contain DEM */ virtual bool IsValidDEMDirectory(const char* DEMDirectory); - /** Open geoid file. */ - virtual void OpenGeoidFile(const char* geoidFile); - virtual void OpenGeoidFile(const std::string& geoidFile); + /** + * \brief Open geoid file given its filename or throw an exception + * if geoid-file could not be loaded. + * + * \param geoidFile The filename of the geoid-file. + * + * \return <code>true</code> if geoid file has been changed or + * <code>false</code> if geod-file have been set before and could + * not be changed. + */ + virtual bool OpenGeoidFile(const char* geoidFile); + + /** + * \brief Open geoid file given its filename or throw an exception + * if geoid-file could not be loaded. + * + * \param geoidFile The filename of the geoid-file. + * + * \return <code>true</code> if geoid file has been changed or + * <code>false</code> if geod-file have been set before and could + * not be changed. + */ + virtual bool OpenGeoidFile(const std::string& geoidFile); /** Compute the height above MSL(Mean Sea Level) of a geographic point. */ virtual double GetHeightAboveMSL(double lon, double lat) const; @@ -125,6 +145,11 @@ public: /** Set the default height above ellipsoid in case no information is available*/ double GetDefaultHeightAboveEllipsoid() const; + /** + * \return The number of elevation databases in the + * <code>ossimElevManager</code>. + */ + unsigned int GetDEMCount() const; /** Get DEM directory */ std::string GetDEMDirectory(unsigned int idx = 0) const; @@ -132,14 +157,18 @@ public: /** Get Goid file */ std::string GetGeoidFile() const; + /** + * \brief Remove all the ossimElevationDatabases from the + * <code>ossimElevManager</code>. + */ + void ClearDEMs(); + protected: DEMHandler(); virtual ~DEMHandler() {} void PrintSelf(std::ostream& os, itk::Indent indent) const; - ossimElevManager* m_ElevManager; - // Ossim does not allow to retrieve the geoid file path // We therefore must keep it on our side std::string m_GeoidFile; diff --git a/Modules/Adapters/OSSIMAdapters/src/otbDEMHandler.cxx b/Modules/Adapters/OSSIMAdapters/src/otbDEMHandler.cxx index 79b352417c22648288dc5a537bf99707a5f24a09..71b94952260fdcba5b6ed9f65a784976b1eaa3e1 100644 --- a/Modules/Adapters/OSSIMAdapters/src/otbDEMHandler.cxx +++ b/Modules/Adapters/OSSIMAdapters/src/otbDEMHandler.cxx @@ -18,6 +18,8 @@ #include "otbDEMHandler.h" #include "otbMacro.h" +#include <cassert> + #include "ossim/elevation/ossimElevManager.h" #include "ossim/base/ossimGeoidManager.h" #include "ossim/base/ossimFilename.h" @@ -49,23 +51,25 @@ DEMHandler::Pointer DEMHandler::Instance() DEMHandler ::DEMHandler() : - m_ElevManager(ossimElevManager::instance()), m_GeoidFile(""), m_DefaultHeightAboveEllipsoid(0) { - m_ElevManager->setDefaultHeightAboveEllipsoid(m_DefaultHeightAboveEllipsoid); + assert( ossimElevManager::instance()!=NULL ); + + ossimElevManager::instance()->setDefaultHeightAboveEllipsoid(m_DefaultHeightAboveEllipsoid); // Force geoid fallback - m_ElevManager->setUseGeoidIfNullFlag(true); + ossimElevManager::instance()->setUseGeoidIfNullFlag(true); } void DEMHandler ::OpenDEMDirectory(const char* DEMDirectory) { - ossimFilename ossimDEMDir; - ossimDEMDir = ossimFilename(DEMDirectory); + assert( ossimElevManager::instance()!=NULL ); + + ossimFilename ossimDEMDir( DEMDirectory ); - if (!m_ElevManager->loadElevationPath(ossimDEMDir)) + if (!ossimElevManager::instance()->loadElevationPath(ossimDEMDir)) { // In ossim elevation database factory code, the // ossimImageElevationDatabase is explicitly disabled by a #if 0 @@ -82,11 +86,22 @@ DEMHandler else { otbMsgDevMacro(<< "DEM directory contains general elevation image files: " << ossimDEMDir); - m_ElevManager->addDatabase(imageElevationDatabase.get()); + ossimElevManager::instance()->addDatabase(imageElevationDatabase.get()); } } } + +void +DEMHandler +::ClearDEMs() +{ + assert( ossimElevManager::instance()!=NULL ); + + ossimElevManager::instance()->clear(); +} + + void DEMHandler ::OpenDEMDirectory(const std::string& DEMDirectory) @@ -98,8 +113,10 @@ bool DEMHandler ::IsValidDEMDirectory(const char* DEMDirectory) { + assert( ossimElevManager::instance()!=NULL ); + //Try to load elevation source - bool result = m_ElevManager->loadElevationPath(DEMDirectory); + bool result = ossimElevManager::instance()->loadElevationPath(DEMDirectory); if (!result) { @@ -111,7 +128,7 @@ DEMHandler return result; } -void +bool DEMHandler ::OpenGeoidFile(const char* geoidFile) { @@ -131,22 +148,31 @@ DEMHandler // The previous flag will be ignored if // defaultHeightAboveEllipsoid is not NaN - m_ElevManager->setDefaultHeightAboveEllipsoid(ossim::nan()); + assert( ossimElevManager::instance()!=NULL ); + ossimElevManager::instance()->setDefaultHeightAboveEllipsoid(ossim::nan()); + + return true; } else { otbMsgDevMacro(<< "Failure opening geoid"); geoidPtr.release(); + + itkExceptionMacro( << "Failed to open geoid file: '" << geoidFile << "'" ); + + return false; } } + + return false; } -void +bool DEMHandler ::OpenGeoidFile(const std::string& geoidFile) { - OpenGeoidFile(geoidFile.c_str()); + return OpenGeoidFile(geoidFile.c_str()); } double @@ -155,9 +181,14 @@ DEMHandler { double height; ossimGpt ossimWorldPoint; + ossimWorldPoint.lon = lon; ossimWorldPoint.lat = lat; - height = m_ElevManager->getHeightAboveMSL(ossimWorldPoint); + + assert( ossimElevManager::instance()!=NULL ); + + height = ossimElevManager::instance()->getHeightAboveMSL(ossimWorldPoint); + return height; } @@ -174,9 +205,13 @@ DEMHandler { double height; ossimGpt ossimWorldPoint; + ossimWorldPoint.lon = lon; ossimWorldPoint.lat = lat; - height = m_ElevManager->getHeightAboveEllipsoid(ossimWorldPoint); + + assert( ossimElevManager::instance()!=NULL ); + + height = ossimElevManager::instance()->getHeightAboveEllipsoid(ossimWorldPoint); return height; } @@ -195,7 +230,10 @@ DEMHandler // Ossim does not allow to retrieve the default height above // ellipsoid We therefore must keep it on our side m_DefaultHeightAboveEllipsoid = h; - m_ElevManager->setDefaultHeightAboveEllipsoid(h); + + assert( ossimElevManager::instance()!=NULL ); + + ossimElevManager::instance()->setDefaultHeightAboveEllipsoid(h); } double @@ -207,13 +245,24 @@ DEMHandler return m_DefaultHeightAboveEllipsoid; } +unsigned int +DEMHandler +::GetDEMCount() const +{ + assert( ossimElevManager::instance()!=NULL ); + + return ossimElevManager::instance()->getNumberOfElevationDatabases(); +} + std::string DEMHandler::GetDEMDirectory(unsigned int idx) const { std::string demDir = ""; - if(m_ElevManager->getNumberOfElevationDatabases() > 0) + if(ossimElevManager::instance()->getNumberOfElevationDatabases() > 0) { - demDir = m_ElevManager->getElevationDatabase(idx)->getConnectionString().string(); + assert( ossimElevManager::instance()!=NULL ); + + demDir = ossimElevManager::instance()->getElevationDatabase(idx)->getConnectionString().string(); } return demDir; } diff --git a/Modules/Adapters/OSSIMAdapters/src/otbImageKeywordlist.cxx b/Modules/Adapters/OSSIMAdapters/src/otbImageKeywordlist.cxx index 0a0309e5f3dba0a46c02262d9a6529903f4fd798..98d873885e84be567549957fb78fa6985d72e2ee 100644 --- a/Modules/Adapters/OSSIMAdapters/src/otbImageKeywordlist.cxx +++ b/Modules/Adapters/OSSIMAdapters/src/otbImageKeywordlist.cxx @@ -139,41 +139,51 @@ bool ImageKeywordlist:: convertToGDALRPC(GDALRPCInfo &rpc) const { - ossimKeywordlist geom_kwl; - - this->convertToOSSIMKeywordlist(geom_kwl); - - if( geom_kwl.hasKey("polynomial_format")) //RK - { - ossimRefPtr<ossimRpcModel> rpcModel = new ossimRpcModel; - if (rpcModel->loadState(geom_kwl)) - { - ossimRpcModel::rpcModelStruct ossimRpcStruct; - rpcModel->getRpcParameters(ossimRpcStruct); + /* ossimRpcModel::loadState() actually expects certain keyword values to be + * present in the keywordlist. So We check a single keyword value + * (polynomial_format) first. Even though it is not enough to ensure a valid + * ossimRpcModel by checking for presence of one single key but atleast we + * are sure about not to create an ossimRpcModel. + * + * The current mechanism creates ossimRpcModel instance, calls loadState() + * and fails. The below check for 'polynomial_format' save us from creating + * an ossimRpcModel which will be invalid if the 'polynomial_format' is not + * present. + */ + if( m_Keywordlist.find("polynomial_format") != m_Keywordlist.end() ) + { + ossimKeywordlist geom_kwl; + this->convertToOSSIMKeywordlist(geom_kwl); - if (ossimRpcStruct.type == 'B') + ossimRefPtr<ossimRpcModel> rpcModel = new ossimRpcModel; + if (rpcModel->loadState(geom_kwl)) { - rpc.dfSAMP_OFF = ossimRpcStruct.sampOffset; - rpc.dfLINE_OFF = ossimRpcStruct.lineOffset; - rpc.dfSAMP_SCALE = ossimRpcStruct.sampScale; - rpc.dfLINE_SCALE = ossimRpcStruct.lineScale; - rpc.dfLAT_OFF = ossimRpcStruct.latOffset; - rpc.dfLONG_OFF = ossimRpcStruct.lonOffset; - rpc.dfHEIGHT_OFF = ossimRpcStruct.hgtOffset; - rpc.dfLAT_SCALE = ossimRpcStruct.latScale; - rpc.dfLONG_SCALE = ossimRpcStruct.lonScale; - rpc.dfHEIGHT_SCALE = ossimRpcStruct.hgtScale; - - memcpy(rpc.adfLINE_NUM_COEFF, ossimRpcStruct.lineNumCoef, sizeof(double) * 20); - memcpy(rpc.adfLINE_DEN_COEFF, ossimRpcStruct.lineDenCoef, sizeof(double) * 20); - memcpy(rpc.adfSAMP_NUM_COEFF, ossimRpcStruct.sampNumCoef, sizeof(double) * 20); - memcpy(rpc.adfSAMP_DEN_COEFF, ossimRpcStruct.sampDenCoef, sizeof(double) * 20); - - return true; + ossimRpcModel::rpcModelStruct ossimRpcStruct; + rpcModel->getRpcParameters(ossimRpcStruct); + + if (ossimRpcStruct.type == 'B') + { + rpc.dfSAMP_OFF = ossimRpcStruct.sampOffset; + rpc.dfLINE_OFF = ossimRpcStruct.lineOffset; + rpc.dfSAMP_SCALE = ossimRpcStruct.sampScale; + rpc.dfLINE_SCALE = ossimRpcStruct.lineScale; + rpc.dfLAT_OFF = ossimRpcStruct.latOffset; + rpc.dfLONG_OFF = ossimRpcStruct.lonOffset; + rpc.dfHEIGHT_OFF = ossimRpcStruct.hgtOffset; + rpc.dfLAT_SCALE = ossimRpcStruct.latScale; + rpc.dfLONG_SCALE = ossimRpcStruct.lonScale; + rpc.dfHEIGHT_SCALE = ossimRpcStruct.hgtScale; + + memcpy(rpc.adfLINE_NUM_COEFF, ossimRpcStruct.lineNumCoef, sizeof(double) * 20); + memcpy(rpc.adfLINE_DEN_COEFF, ossimRpcStruct.lineDenCoef, sizeof(double) * 20); + memcpy(rpc.adfSAMP_NUM_COEFF, ossimRpcStruct.sampNumCoef, sizeof(double) * 20); + memcpy(rpc.adfSAMP_DEN_COEFF, ossimRpcStruct.sampDenCoef, sizeof(double) * 20); + + return true; + } } - } - } - return false; + } + return false; } void diff --git a/Modules/Adapters/OSSIMAdapters/test/CMakeLists.txt b/Modules/Adapters/OSSIMAdapters/test/CMakeLists.txt index d11608709f0552643a238bb01042453df869e9d2..42440cd9a65cea1d85f0099a6ba1760664f64e8e 100644 --- a/Modules/Adapters/OSSIMAdapters/test/CMakeLists.txt +++ b/Modules/Adapters/OSSIMAdapters/test/CMakeLists.txt @@ -441,6 +441,7 @@ otb_add_test(NAME uaTvDEMHandler_AboveEllipsoid_SRTM_BadGeoid COMMAND otbOSSIMAd 339.513 0.001 ) +set_property(TEST uaTvDEMHandler_AboveEllipsoid_SRTM_BadGeoid PROPERTY WILL_FAIL true) otb_add_test(NAME uaTvDEMHandler_AboveMSL_SRTM_NoGeoid_NoData COMMAND otbOSSIMAdaptersTestDriver otbDEMHandlerTest diff --git a/Modules/Adapters/OSSIMAdapters/test/otbDEMHandlerTest.cxx b/Modules/Adapters/OSSIMAdapters/test/otbDEMHandlerTest.cxx index 9987db6a5bcd5cd74ac0793cd8e5b0aaea5261f2..09ab37cf7c098c990a0668f176099eda0109ab94 100644 --- a/Modules/Adapters/OSSIMAdapters/test/otbDEMHandlerTest.cxx +++ b/Modules/Adapters/OSSIMAdapters/test/otbDEMHandlerTest.cxx @@ -59,7 +59,19 @@ int otbDEMHandlerTest(int argc, char * argv[]) if(geoid != "no") { - demHandler->OpenGeoidFile(geoid); + try + { + demHandler->OpenGeoidFile(geoid); + } + catch( const std::exception & exception ) + { + std::cout + << "Exception thrown while opening geod-file '" << geoid << "':" << std::endl + << exception.what(); + + fail = true; + } + std::cout<<"GetGeoidFile() = "<<demHandler->GetGeoidFile()<<std::endl; }