DEMHandlerExample.cxxΒΆ

Example usage:

./DEMHandlerExample Input/DEM/srtm_directory Input/DEM/egm96.grd 40 8.434583 44.647083 383.580313671 0.001

Example source code (DEMHandlerExample.cxx):

// Since release 8.0, OTB relies on GDAL for elevation handling. Since release 3.16,
// there is a single configuration class \doxygen{otb}{DEMHandler} to manage elevation
// (in image projections or localization functions for example). This configuration
// is managed by the a proper instantiation and parameters setting of this
// class. These instantiations must be done before any call to geometric
// filters or functionalities. GDAL internal accesses to elevation are also
// configured by this class and this will ensure consistency throughout the
// library.

#include "otbDEMHandler.h"

int main(int argc, char* argv[])
{
  if (argc != 8)
  {
    std::cerr << "Usage: " << argv[0] << " demdir[path|no] geoid[path|no] defaultHeight longitude latitude targetValue tolerance" << std::endl;
    return EXIT_FAILURE;
  }

  std::string demdir        = argv[1];
  std::string geoid         = argv[2];
  double      defaultHeight = atof(argv[3]);
  double      longitude     = atof(argv[4]);
  double      latitude      = atof(argv[5]);
  double      target        = atof(argv[6]);
  double      tolerance     = atof(argv[7]);

  // This class is a singleton, the New() method is deprecated and will be removed
  // in future release. We need to use the \code{Instance()} method instead.

  auto & demHandler = otb::DEMHandler::GetInstance();

  bool fail = false;

  // It allows configuring a directory containing DEM tiles (DTED or SRTM
  // supported) using the \code{OpenDEMDirectory()} method. The \code{OpenGeoidFile()} method
  // allows inputting a geoid file as well. Last, a default height above ellipsoid
  // can be set using the \code{SetDefaultHeightAboveEllipsoid()} method.

  demHandler.SetDefaultHeightAboveEllipsoid(defaultHeight);

  if (!demHandler.IsValidDEMDirectory(demdir.c_str()))
  {
    std::cerr << "IsValidDEMDirectory(" << demdir << ") = false" << std::endl;
    fail = true;
  }

  demHandler.OpenDEMDirectory(demdir);
  demHandler.OpenGeoidFile(geoid);

  // We can now retrieve height above ellipsoid or height above Mean Sea Level
  // (MSL) using the methods \code{GetHeightAboveEllipsoid()} and
  // \code{GetHeightAboveMSL()}.  Outputs of these methods depend on the
  // configuration of the class \doxygen{otb}{DEMHandler} and the different
  // cases are:
  //
  // For \code{GetHeightAboveEllipsoid()}:
  //
  // \begin{itemize}
  // \item DEM and geoid both available: $dem\_value + geoid\_offset$
  // \item No DEM but geoid available: geoid\_offset
  // \item DEM available, but no geoid: dem\_value
  // \item No DEM and no geoid available: default height above ellipsoid
  // \end{itemize}
  //
  // For \code{GetHeightAboveMSL()}:
  //
  // \begin{itemize}
  // \item DEM and geoid both available: srtm\_value
  // \item No DEM but geoid available: $0$
  // \item DEM available, but no geoid: srtm\_value
  // \item No DEM and no geoid available: $0$
  // \end{itemize}

  otb::DEMHandler::PointType point;
  point[0] = longitude;
  point[1] = latitude;

  double height = -32768;

  height = demHandler.GetHeightAboveMSL(point);
  std::cout << "height above MSL (" << longitude << "," << latitude << ") = " << height << " meters" << std::endl;

  height = demHandler.GetHeightAboveEllipsoid(point);
  std::cout << "height above ellipsoid (" << longitude << ", " << latitude << ") = " << height << " meters" << std::endl;

  // Check for Nan
  if (vnl_math_isnan(height))
  {
    std::cerr << "Computed value is NaN" << std::endl;
    fail = true;
  }

  double error = std::abs(height - target);

  if (error > tolerance)
  {
    std::cerr << "Target value is " << target << " meters, computed value is " << height << " meters. error (" << error << " meters) > tolerance (" << tolerance
              << " meters)" << std::endl;
    fail = true;
  }

  if (fail)
  {
    return EXIT_FAILURE;
  }

  return EXIT_SUCCESS;
}