Skip to content
Snippets Groups Projects
Forked from Main Repositories / otb
17540 commits behind the upstream repository.
otbSensorModelAdapter.cxx 7.24 KiB
/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$


  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.


     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "otbSensorModelAdapter.h"

#include <cassert>

#include "otbMacro.h"
#include "otbImageKeywordlist.h"

#include "ossim/projection/ossimProjection.h"
#include "ossim/projection/ossimSensorModelFactory.h"
#include "ossim/projection/ossimSensorModel.h"
#include "ossim/ossimPluginProjectionFactory.h"
#include "ossim/base/ossimTieGptSet.h"

namespace otb
{

namespace internal
{
  /**
   * Converts index coordinates from OTB into OSSIM. It is intended for sensor
   * images where the centre of the top-left pixel is expected to be :
   *   [0.5,0.5] in OTB
   *   [ 0 , 0 ] in OSSIM
   */
  void ConvertOTBToOSSIMCoordinates(ossimDpt &pt)
  {
    pt.x = pt.x - 0.5;
    pt.y = pt.y - 0.5;
  }

  /**
   * Converts index coordinates from OSSIM into OTB. It is intended for sensor
   * images where the centre of the top-left pixel is expected to be :
   *   [0.5,0.5] in OTB
   *   [ 0 , 0 ] in OSSIM
   */
  void ConvertOSSIMToOTBCoordinates(ossimDpt &pt)
  {
    pt.x = pt.x + 0.5;
    pt.y = pt.y + 0.5;
  }

} // namespace internal


SensorModelAdapter::SensorModelAdapter():
  m_SensorModel(NULL), m_TiePoints(NULL) // FIXME keeping the original value but...
{
  m_DEMHandler = DEMHandler::Instance();
  m_TiePoints = new ossimTieGptSet();
}
SensorModelAdapter::~SensorModelAdapter()
{
  if (m_SensorModel != NULL)
    {
    delete m_SensorModel;
    m_SensorModel = NULL;
    }
  if(m_TiePoints!=NULL)
    {
    delete m_TiePoints;
    m_TiePoints = NULL;
    }
}

void SensorModelAdapter::CreateProjection(const ImageKeywordlist& image_kwl)
{
  ossimKeywordlist geom;

  image_kwl.convertToOSSIMKeywordlist(geom);
  otbMsgDevMacro(<< "CreateProjection()");
  otbMsgDevMacro(<< "* type: " << geom.find("type"));

  m_SensorModel = ossimSensorModelFactory::instance()->createProjection(geom);
  if (m_SensorModel == NULL)
    {
      m_SensorModel = ossimplugins::ossimPluginProjectionFactory::instance()->createProjection(geom);
    }
}

bool SensorModelAdapter::IsValidSensorModel()
{
  if (m_SensorModel == NULL)
    {
      return false;
    }
  else
    {
      return true;
    }
}

void SensorModelAdapter::ForwardTransformPoint(double x, double y, double z,
                                               double& lon, double& lat, double& h) const
{
  if (this->m_SensorModel == NULL)
    {
    itkExceptionMacro(<< "ForwardTransformPoint(): Invalid sensor model (m_SensorModel pointer is null)");
    }

  ossimDpt ossimPoint(x, y);
  ossimGpt ossimGPoint;

  internal::ConvertOTBToOSSIMCoordinates(ossimPoint);
  this->m_SensorModel->lineSampleHeightToWorld(ossimPoint,z, ossimGPoint);

  lon = ossimGPoint.lon;
  lat = ossimGPoint.lat;
  h = ossimGPoint.hgt;
}

void SensorModelAdapter::ForwardTransformPoint(double x, double y,
                                               double& lon, double& lat, double& h) const
{
  if (this->m_SensorModel == NULL)
    {
    itkExceptionMacro(<< "ForwardTransformPoint(): Invalid sensor model (m_SensorModel pointer is null)");
    }

  ossimDpt ossimPoint(x, y);
  ossimGpt ossimGPoint;

  internal::ConvertOTBToOSSIMCoordinates(ossimPoint);
  this->m_SensorModel->lineSampleToWorld(ossimPoint, ossimGPoint);

  lon = ossimGPoint.lon;
  lat = ossimGPoint.lat;
  h = ossimGPoint.hgt;
}

void SensorModelAdapter::InverseTransformPoint(double lon, double lat, double h,
                                               double& x, double& y, double& z) const
{
  if (this->m_SensorModel == NULL)
    {
    itkExceptionMacro(<< "InverseTransformPoint(): Invalid sensor model (m_SensorModel pointer is null)");
    }

  // Initialize with value from the function parameters
  ossimGpt ossimGPoint(lat, lon, h);
  ossimDpt ossimDPoint;

  this->m_SensorModel->worldToLineSample(ossimGPoint, ossimDPoint);
  internal::ConvertOSSIMToOTBCoordinates(ossimDPoint);

  x = ossimDPoint.x;
  y = ossimDPoint.y;
  z = ossimGPoint.height();
}


void SensorModelAdapter::InverseTransformPoint(double lon, double lat,
                                               double& x, double& y, double& z) const
{
  if (this->m_SensorModel == NULL)
    {
    itkExceptionMacro(<< "InverseTransformPoint(): Invalid sensor model (m_SensorModel pointer is null)");
    }

  // Get elevation from DEMHandler
  double h = m_DEMHandler->GetHeightAboveEllipsoid(lon,lat);

  // Initialize with value from the function parameters
  ossimGpt ossimGPoint(lat, lon, h);
  ossimDpt ossimDPoint;

  this->m_SensorModel->worldToLineSample(ossimGPoint, ossimDPoint);
  internal::ConvertOSSIMToOTBCoordinates(ossimDPoint);

  x = ossimDPoint.x;
  y = ossimDPoint.y;
  z = ossimGPoint.height();
}

void SensorModelAdapter::AddTiePoint(double x, double y, double z, double lon, double lat)
{
  // Create the tie point
  ossimDpt imagePoint(x,y);
  ossimGpt ossimGPoint(lat, lon, z);
  internal::ConvertOTBToOSSIMCoordinates(imagePoint);

  // Add the tie point to the container
  m_TiePoints->addTiePoint(new ossimTieGpt(ossimGPoint,imagePoint,0));
}

void SensorModelAdapter::AddTiePoint(double x, double y, double lon, double lat)
{
  // Create the tie point
  ossimDpt imagePoint(x,y);
  internal::ConvertOTBToOSSIMCoordinates(imagePoint);
  // Get elevation from DEMHandler
  double z = m_DEMHandler->GetHeightAboveEllipsoid(lon,lat);

  ossimGpt ossimGPoint(lat, lon, z);

  // Add the tie point to the container
  m_TiePoints->addTiePoint(new ossimTieGpt(ossimGPoint,imagePoint,0));
}


void SensorModelAdapter::ClearTiePoints()
{
  m_TiePoints->clearTiePoints();
}

double SensorModelAdapter::Optimize()
{
  double precision = 0.;

  // If tie points and model are allocated
  if(m_SensorModel != NULL)
    {
    // try to retrieve a sensor model
    ossimSensorModel * sensorModel = NULL;
    sensorModel = dynamic_cast<ossimSensorModel *>(m_SensorModel);

    if(sensorModel != NULL)
      {
      // Call optimize fit
      precision  = sensorModel->optimizeFit(*m_TiePoints);
      }
    }

  // Return the precision
  return precision;
}

bool SensorModelAdapter::ReadGeomFile(const std::string & infile)
{
  ossimKeywordlist geom;

  geom.add(infile.c_str());

  m_SensorModel = ossimSensorModelFactory::instance()->createProjection(geom);

  if (m_SensorModel == NULL)
    {
    m_SensorModel = ossimplugins::ossimPluginProjectionFactory::instance()->createProjection(geom);
    }

  return (m_SensorModel != NULL);
}

bool SensorModelAdapter::WriteGeomFile(const std::string & outfile)
{
  // If tie points and model are allocated
  if(m_SensorModel != NULL)
    {
    // try to retrieve a sensor model
    ossimSensorModel * sensorModel = NULL;
    sensorModel = dynamic_cast<ossimSensorModel *>(m_SensorModel);

    ossimKeywordlist geom;

    bool success = sensorModel->saveState(geom);

    if(success)
      {
      return geom.write(outfile.c_str());
      }
    }
  return false;
}

} // namespace otb