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