From d4f36fd349b90ec6a333358a9d6df40f484dce23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Traizet?= <cedric.traizet@c-s.fr> Date: Tue, 21 Jul 2020 17:37:49 +0200 Subject: [PATCH] REFAC: renamed the DEMHandler class from OSSIMAdapters into OssimDEMHandler --- .../include/otbOssimDEMHandler.h | 191 ++++++++++++ .../OSSIMAdapters/src/otbOssimDEMHandler.cxx | 275 ++++++++++++++++++ 2 files changed, 466 insertions(+) create mode 100644 Modules/Adapters/OSSIMAdapters/include/otbOssimDEMHandler.h create mode 100644 Modules/Adapters/OSSIMAdapters/src/otbOssimDEMHandler.cxx diff --git a/Modules/Adapters/OSSIMAdapters/include/otbOssimDEMHandler.h b/Modules/Adapters/OSSIMAdapters/include/otbOssimDEMHandler.h new file mode 100644 index 0000000000..16a4002e04 --- /dev/null +++ b/Modules/Adapters/OSSIMAdapters/include/otbOssimDEMHandler.h @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2005-2020 Centre National d'Etudes Spatiales (CNES) + * + * This file is part of Orfeo Toolbox + * + * https://www.orfeo-toolbox.org/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef otbOssimDEMHandler_h +#define otbOssimDEMHandler_h + +#include <cstdio> + +#include "itkIndent.h" +#include "itkObject.h" +#include "itkObjectFactory.h" +#include "itkPoint.h" + +#include "OTBOSSIMAdaptersExport.h" +#include <string> + +class ossimElevManager; + +namespace otb +{ +/** \class OssimDEMHandler + * + * \brief Single access point for DEM data retrieval + * + * This class is the single configuration and access point for + * elevation handling in images projections and localization + * functions. Since this class is a singleton, there is no New() method. The + * OssimDEMHandler::Instance() method should be used instead. + * + * Please be aware that a proper instantiation and parameter setting + * of this class is advised before any call to geometric filters or + * functionalities. Ossim internal accesses to elevation are also + * configured by this class and this will ensure consistency + * throughout the library. + * + * The class allows configuring a directory containing DEM tiles + * (DTED or SRTM supported) using the OpenDEMDirectory() method. The + * OpenGeoidFile() method allows inputting a geoid file as well. Last, + * a default height above ellipsoid can be set using the + * SetDefaultHeightAboveEllipsoid() method. + * + * The class allows retrieving either height above ellipsoid or + * height above Mean Sea Level (MSL). + * + * Here is the complete description of both methods output depending + * on the class configuration for the SRTM DEM (in the following, no + * SRTM means DEMDirectory not set, or no coverage for point, or + * srtm_value is no_data). + * + * GetHeightAboveEllipsoid(): + * - SRTM and geoid both available: srtm_value + geoid_offset + * - No SRTM but geoid available: geoid_offset + * - SRTM available, but no geoid: srtm_value + * - No SRTM and no geoid available: default height above ellipsoid + * + * GetHeightAboveMSL(): + * - SRTM and geoid both available: srtm_value + * - No SRTM but geoid available: 0 + * - SRTM available, but no geoid: srtm_value + * - No SRTM and no geoid available: 0 + * + * Please note that OSSIM internal calls for sensor modeling use the + * height above ellipsoid, and follow the same logic as the + * GetHeightAboveEllipsoid() method. + * + * DEM directory can either contain DTED or SRTM formats. + * \ingroup Images + * + * + * \ingroup OTBOSSIMAdapters + */ + +class OTBOSSIMAdapters_EXPORT OssimDEMHandler : public itk::Object +{ +public: + /** Standard class typedefs. */ + typedef OssimDEMHandler Self; + typedef itk::Object Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + + typedef itk::Point<double, 2> PointType; + + /** Retrieve the singleton instance */ + static Pointer Instance(); + + /** Run-time type information (and related methods). */ + itkTypeMacro(OssimDEMHandler, Object); + + /** Try to open the DEM directory. */ + virtual void OpenDEMDirectory(const char* DEMDirectory); + virtual void OpenDEMDirectory(const std::string& DEMDirectory); + + /** return true if the directory contain DEM */ + virtual bool IsValidDEMDirectory(const char* DEMDirectory); + + /** + * \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; + virtual double GetHeightAboveMSL(const PointType& geoPoint) const; + + /** Compute the height above ellipsoid of a geographic point. */ + virtual double GetHeightAboveEllipsoid(double lon, double lat) const; + virtual double GetHeightAboveEllipsoid(const PointType& geoPoint) const; + + /** Set the default height above ellipsoid in case no information is available*/ + virtual void SetDefaultHeightAboveEllipsoid(double h); + + /** 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; + + /** Get Goid file */ + std::string GetGeoidFile() const; + + /** + * \brief Remove all the ossimElevationDatabases from the + * <code>ossimElevManager</code>. + */ + void ClearDEMs(); + +protected: + OssimDEMHandler(); + ~OssimDEMHandler() override + { + } + + void PrintSelf(std::ostream& os, itk::Indent indent) const override; + + // Ossim does not allow retrieving the geoid file path + // We therefore must keep it on our side + std::string m_GeoidFile; + + // Ossim does not allow retrieving the default height above + // ellipsoid We therefore must keep it on our side + double m_DefaultHeightAboveEllipsoid; + + static Pointer m_Singleton; +}; + +} // namespace otb + +#endif diff --git a/Modules/Adapters/OSSIMAdapters/src/otbOssimDEMHandler.cxx b/Modules/Adapters/OSSIMAdapters/src/otbOssimDEMHandler.cxx new file mode 100644 index 0000000000..fd318266ed --- /dev/null +++ b/Modules/Adapters/OSSIMAdapters/src/otbOssimDEMHandler.cxx @@ -0,0 +1,275 @@ +/* + * Copyright (C) 2005-2020 Centre National d'Etudes Spatiales (CNES) + * + * This file is part of Orfeo Toolbox + * + * https://www.orfeo-toolbox.org/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "otbOssimDEMHandler.h" +#include "otbMacro.h" + +#include <cassert> + +#include "otb_ossim.h" + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Woverloaded-virtual" +#pragma GCC diagnostic ignored "-Wshadow" +#include "ossim/elevation/ossimElevManager.h" +#include "ossim/base/ossimGeoidManager.h" +#include "ossim/base/ossimFilename.h" +#include "ossim/base/ossimDirectory.h" +#include "ossim/base/ossimGeoidEgm96.h" +#include "ossim/base/ossimRefPtr.h" +#include <ossim/elevation/ossimImageElevationDatabase.h> +#pragma GCC diagnostic pop +#else +#include "ossim/elevation/ossimElevManager.h" +#include "ossim/base/ossimGeoidManager.h" +#include "ossim/base/ossimFilename.h" +#include "ossim/base/ossimDirectory.h" +#include "ossim/base/ossimGeoidEgm96.h" +#include "ossim/base/ossimRefPtr.h" +#include <ossim/elevation/ossimImageElevationDatabase.h> +#endif + + +namespace otb +{ +/** Initialize the singleton */ +OssimDEMHandler::Pointer OssimDEMHandler::m_Singleton = nullptr; + +OssimDEMHandler::Pointer OssimDEMHandler::Instance() +{ + if (m_Singleton.GetPointer() == nullptr) + { + m_Singleton = itk::ObjectFactory<Self>::Create(); + + if (m_Singleton.GetPointer() == nullptr) + { + m_Singleton = new OssimDEMHandler; + } + m_Singleton->UnRegister(); + } + + return m_Singleton; +} + +OssimDEMHandler::OssimDEMHandler() : m_GeoidFile(""), m_DefaultHeightAboveEllipsoid(0) +{ + assert(ossimElevManager::instance() != NULL); + + ossimElevManager::instance()->setDefaultHeightAboveEllipsoid(m_DefaultHeightAboveEllipsoid); + // Force geoid fallback + ossimElevManager::instance()->setUseGeoidIfNullFlag(true); +} + +void OssimDEMHandler::OpenDEMDirectory(const char* DEMDirectory) +{ + assert(ossimElevManager::instance() != NULL); + + ossimFilename ossimDEMDir(DEMDirectory); + + if (!ossimElevManager::instance()->loadElevationPath(ossimDEMDir)) + { + // In ossim elevation database factory code, the + // ossimImageElevationDatabase is explicitly disabled by a #if 0 + // guard, because it causes problem when loading ossim related + // application. Therefore, we explicitly call + // ossimImageElevationDatabase here to allow for general elevation + // images support. + ossimRefPtr<ossimElevationDatabase> imageElevationDatabase = new ossimImageElevationDatabase; + + if (!imageElevationDatabase->open(DEMDirectory)) + { + itkExceptionMacro("Failed to open DEM Directory: " << ossimDEMDir); + } + else + { + otbMsgDevMacro(<< "DEM directory contains general elevation image files: " << ossimDEMDir); + ossimElevManager::instance()->addDatabase(imageElevationDatabase.get()); + } + } +} + + +void OssimDEMHandler::ClearDEMs() +{ + assert(ossimElevManager::instance() != NULL); + + ossimElevManager::instance()->clear(); +} + + +void OssimDEMHandler::OpenDEMDirectory(const std::string& DEMDirectory) +{ + OpenDEMDirectory(DEMDirectory.c_str()); +} + +bool OssimDEMHandler::IsValidDEMDirectory(const char* DEMDirectory) +{ + assert(ossimElevManager::instance() != NULL); + + // Try to load elevation source + bool result = ossimElevManager::instance()->loadElevationPath(DEMDirectory); + + if (!result) + { + // we explicitly call ossimImageElevationDatabase here to allow for general elevation + // images support and test the open method to check if the directory . + ossimRefPtr<ossimElevationDatabase> imageElevationDatabase = new ossimImageElevationDatabase; + result = imageElevationDatabase->open(DEMDirectory); + } + return result; +} + +bool OssimDEMHandler::OpenGeoidFile(const char* geoidFile) +{ + if ((ossimGeoidManager::instance()->findGeoidByShortName("geoid1996")) == nullptr) + { + otbMsgDevMacro(<< "Opening geoid: " << geoidFile); + ossimFilename geoid(geoidFile); + ossimRefPtr<ossimGeoid> geoidPtr = new ossimGeoidEgm96(geoid); + if (geoidPtr->getErrorStatus() == ossimErrorCodes::OSSIM_OK) + { + // Ossim does not allow retrieving the geoid file path + // We therefore must keep it on our side + m_GeoidFile = geoidFile; + otbMsgDevMacro(<< "Geoid successfully opened"); + ossimGeoidManager::instance()->addGeoid(geoidPtr); + geoidPtr.release(); + + // The previous flag will be ignored if + // defaultHeightAboveEllipsoid is not 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; +} + +bool OssimDEMHandler::OpenGeoidFile(const std::string& geoidFile) +{ + return OpenGeoidFile(geoidFile.c_str()); +} + +double OssimDEMHandler::GetHeightAboveMSL(double lon, double lat) const +{ + double height; + ossimGpt ossimWorldPoint; + + ossimWorldPoint.lon = lon; + ossimWorldPoint.lat = lat; + + assert(ossimElevManager::instance() != NULL); + + height = ossimElevManager::instance()->getHeightAboveMSL(ossimWorldPoint); + + return height; +} + +double OssimDEMHandler::GetHeightAboveMSL(const PointType& geoPoint) const +{ + return GetHeightAboveMSL(geoPoint[0], geoPoint[1]); +} + +double OssimDEMHandler::GetHeightAboveEllipsoid(double lon, double lat) const +{ + double height; + ossimGpt ossimWorldPoint; + + ossimWorldPoint.lon = lon; + ossimWorldPoint.lat = lat; + + assert(ossimElevManager::instance() != NULL); + + height = ossimElevManager::instance()->getHeightAboveEllipsoid(ossimWorldPoint); + + return height; +} + +double OssimDEMHandler::GetHeightAboveEllipsoid(const PointType& geoPoint) const +{ + return GetHeightAboveEllipsoid(geoPoint[0], geoPoint[1]); +} + +void OssimDEMHandler::SetDefaultHeightAboveEllipsoid(double h) +{ + // Ossim does not allow retrieving the default height above + // ellipsoid We therefore must keep it on our side + m_DefaultHeightAboveEllipsoid = h; + + assert(ossimElevManager::instance() != NULL); + + ossimElevManager::instance()->setDefaultHeightAboveEllipsoid(h); +} + +double OssimDEMHandler::GetDefaultHeightAboveEllipsoid() const +{ + // Ossim does not allow retrieving the default height above + // ellipsoid We therefore must keep it on our side + return m_DefaultHeightAboveEllipsoid; +} + +unsigned int OssimDEMHandler::GetDEMCount() const +{ + assert(ossimElevManager::instance() != NULL); + + return ossimElevManager::instance()->getNumberOfElevationDatabases(); +} + +std::string OssimDEMHandler::GetDEMDirectory(unsigned int idx) const +{ + std::string demDir = ""; + + if (ossimElevManager::instance()->getNumberOfElevationDatabases() > 0) + { + assert(ossimElevManager::instance() != NULL); + + demDir = ossimElevManager::instance()->getElevationDatabase(idx)->getConnectionString().string(); + } + return demDir; +} + +std::string OssimDEMHandler::GetGeoidFile() const +{ + // Ossim does not allow retrieving the geoid file path + // We therefore must keep it on our side + return m_GeoidFile; +} + +void OssimDEMHandler::PrintSelf(std::ostream& os, itk::Indent indent) const +{ + Superclass::PrintSelf(os, indent); + os << indent << "OssimDEMHandler" << std::endl; +} + +} // namespace otb -- GitLab