Commit 348177a9 authored by Julien Osman's avatar Julien Osman
Browse files

Merge branch '2150-factory-sensor-transforms' into 'develop'

Implement a factory for sensor transforms

Closes #2150

See merge request !806
parents 06939888 dab79955
Pipeline #8151 passed with stages
in 20 minutes and 48 seconds
......@@ -61,6 +61,7 @@ Laurențiu Nicola <lnicola@dend.ro> Laurentiu Nicola <lni
Laurențiu Nicola <lnicola@dend.ro> Laurențiu Nicola <grayshade@gmail.com>
Luc Hermitte <luc.hermitte@csgroup.eu> Luc Hermitte <luc.hermitte@cnes.fr>
Luc Hermitte <luc.hermitte@csgroup.eu> Luc Hermitte <luc.hermitte@c-s.fr>
Luc Hermitte <luc.hermitte@csgroup.eu> Luc Hermitte <9-lhermitte@users.noreply.gitlab.orfeo-toolbox.org>
Ludovic Hussonnois <ludovic.hussonnois@c-s.fr>
Manuel Grizonnet <manuel.grizonnet@cnes.fr>
Manuel Grizonnet <manuel.grizonnet@cnes.fr> Grizonnet Manuel <manuel.grizonnet@cnes.fr>
......
......@@ -35,3 +35,21 @@ description from the ``otb::ImageMetadata`` and instantiates an
The classes ``otb::RPCForwardTransform`` and
``otb::RPCInverseTransform`` each implement a version of the
``TransformPoint`` method which uses the ``otb::GDALRPCTransformer``.
Sensor Transform Factory
------------------------
The class ``SensorTransformFactory`` is designed to automatically
instanciate the best sensor transform based on the available
metadata. One should use the function ``CreateTransform`` which is
templated over the scalar type used in the transform and the
dimensions of the input and output spaces. It takes as parameters a
pointer to the ImageMetadata object, and the direction of the
transform (either FORWARD or INVERSE). It returns a std::unique_ptr to
the transform object.
.. code-block:: cpp
#include "otbSensorTransformFactory.h"
auto sensorModel = otb::SensorTransformFactory::GetInstance().CreateTransform <double, 2, 3>(imageMetadataPointer, TransformDirection::FORWARD);
auto worldPoint = sensorModel->TransformPoint(sensorPoint);
......@@ -30,16 +30,6 @@
namespace otb
{
namespace TransformDirection
{
enum TransformationDirection
{
FORWARD = 0,
INVERSE = 1
};
}
/** \class GenericMapProjection
* \brief This is the base class for generic map projection transformation
*
......@@ -55,7 +45,7 @@ enum TransformationDirection
* \ingroup OTBTransform
**/
template <TransformDirection::TransformationDirection TDirectionOfMapping, class TScalarType = double, unsigned int NInputDimensions = 2,
template <TransformDirection TDirectionOfMapping, class TScalarType = double, unsigned int NInputDimensions = 2,
unsigned int NOutputDimensions = 2>
class ITK_EXPORT GenericMapProjection : public Transform<TScalarType, // Data type for scalars
NInputDimensions, // Number of dimensions in the input space
......@@ -78,7 +68,7 @@ public:
/** Run-time type information (and related methods). */
itkTypeMacro(GenericMapProjection, Transform);
static const TransformDirection::TransformationDirection DirectionOfMapping = TDirectionOfMapping;
static const TransformDirection DirectionOfMapping = TDirectionOfMapping;
itkStaticConstMacro(InputSpaceDimension, unsigned int, NInputDimensions);
itkStaticConstMacro(OutputSpaceDimension, unsigned int, NOutputDimensions);
......
......@@ -27,18 +27,18 @@
namespace otb
{
template <TransformDirection::TransformationDirection TDirectionOfMapping, class TScalarType, unsigned int NInputDimensions, unsigned int NOutputDimensions>
template <TransformDirection TDirectionOfMapping, class TScalarType, unsigned int NInputDimensions, unsigned int NOutputDimensions>
GenericMapProjection<TDirectionOfMapping, TScalarType, NInputDimensions, NOutputDimensions>::GenericMapProjection()
: Superclass(ParametersDimension), m_MapProjection()
{
}
template <TransformDirection::TransformationDirection TDirectionOfMapping, class TScalarType, unsigned int NInputDimensions, unsigned int NOutputDimensions>
template <TransformDirection TDirectionOfMapping, class TScalarType, unsigned int NInputDimensions, unsigned int NOutputDimensions>
GenericMapProjection<TDirectionOfMapping, TScalarType, NInputDimensions, NOutputDimensions>::~GenericMapProjection()
{
}
template <TransformDirection::TransformationDirection TDirectionOfMapping, class TScalarType, unsigned int NInputDimensions, unsigned int NOutputDimensions>
template <TransformDirection TDirectionOfMapping, class TScalarType, unsigned int NInputDimensions, unsigned int NOutputDimensions>
std::string GenericMapProjection<TDirectionOfMapping, TScalarType, NInputDimensions, NOutputDimensions>::GetWkt()
{
if (m_MapProjection)
......@@ -56,7 +56,7 @@ std::string GenericMapProjection<TDirectionOfMapping, TScalarType, NInputDimensi
return "";
}
template <TransformDirection::TransformationDirection TDirectionOfMapping, class TScalarType, unsigned int NInputDimensions, unsigned int NOutputDimensions>
template <TransformDirection TDirectionOfMapping, class TScalarType, unsigned int NInputDimensions, unsigned int NOutputDimensions>
void GenericMapProjection<TDirectionOfMapping, TScalarType, NInputDimensions, NOutputDimensions>::SetWkt(const std::string& projectionRefWkt)
{
SpatialReference wgs84 = SpatialReference::FromWGS84();
......@@ -85,7 +85,7 @@ void GenericMapProjection<TDirectionOfMapping, TScalarType, NInputDimensions, NO
this->Modified();
}
template <TransformDirection::TransformationDirection TDirectionOfMapping, class TScalarType, unsigned int NInputDimensions, unsigned int NOutputDimensions>
template <TransformDirection TDirectionOfMapping, class TScalarType, unsigned int NInputDimensions, unsigned int NOutputDimensions>
typename GenericMapProjection<TDirectionOfMapping, TScalarType, NInputDimensions, NOutputDimensions>::OutputPointType
GenericMapProjection<TDirectionOfMapping, TScalarType, NInputDimensions, NOutputDimensions>::TransformPoint(const InputPointType& point) const
{
......@@ -124,13 +124,13 @@ GenericMapProjection<TDirectionOfMapping, TScalarType, NInputDimensions, NOutput
}
template <TransformDirection::TransformationDirection TDirectionOfMapping, class TScalarType, unsigned int NInputDimensions, unsigned int NOutputDimensions>
template <TransformDirection TDirectionOfMapping, class TScalarType, unsigned int NInputDimensions, unsigned int NOutputDimensions>
bool GenericMapProjection<TDirectionOfMapping, TScalarType, NInputDimensions, NOutputDimensions>::IsProjectionDefined() const
{
return m_MapProjection != nullptr;
}
template <TransformDirection::TransformationDirection TDirectionOfMapping, class TScalarType, unsigned int NInputDimensions, unsigned int NOutputDimensions>
template <TransformDirection TDirectionOfMapping, class TScalarType, unsigned int NInputDimensions, unsigned int NOutputDimensions>
void GenericMapProjection<TDirectionOfMapping, TScalarType, NInputDimensions, NOutputDimensions>::PrintSelf(std::ostream& os, itk::Indent indent) const
{
Superclass::PrintSelf(os, indent);
......
......@@ -23,6 +23,7 @@
#include "otbCompositeTransform.h"
#include "otbImageMetadata.h"
#include "otbSensorTransformFactory.h"
#include <string>
namespace otb
......@@ -87,7 +88,7 @@ public:
/** Run-time type information (and related methods). */
itkTypeMacro(GenericRSTransform, Transform);
typedef TransformDirection::TransformationDirection DirectionOfMappingEnumType;
typedef TransformDirection DirectionOfMappingEnumType;
itkStaticConstMacro(InputSpaceDimension, unsigned int, NInputDimensions);
itkStaticConstMacro(OutputSpaceDimension, unsigned int, NOutputDimensions);
......@@ -178,6 +179,7 @@ protected:
GenericRSTransform();
~GenericRSTransform() override
{
// SensorTransformFactory<TScalarType, NInputDimensions, NOutputDimensions>::CleanFactories();
}
void Modified() const override
......
......@@ -29,6 +29,7 @@
#include "otbSpatialReference.h"
#include "ogr_spatialref.h"
#include "otbSensorTransformFactory.h"
namespace otb
{
......@@ -119,12 +120,10 @@ void GenericRSTransform<TScalarType, NInputDimensions, NOutputDimensions>::Insta
// If not, try to make a RPC sensor model
if ((m_InputTransform.IsNull()) && (m_InputImd != nullptr) && (m_InputImd->Has(MDGeom::RPC)))
{
typedef otb::RPCForwardTransform<double, InputSpaceDimension, OutputSpaceDimension> RPCForwardTransformType;
typename RPCForwardTransformType::Pointer sensorModel = RPCForwardTransformType::New();
auto sensorModel = otb::SensorTransformFactory::GetInstance().CreateTransform
<double, InputSpaceDimension, OutputSpaceDimension>(*m_InputImd,TransformDirection::FORWARD);
sensorModel->SetMetadata(*m_InputImd);
if (sensorModel->IsValidSensorModel())
if (sensorModel != nullptr)
{
m_InputTransform = sensorModel.GetPointer();
inputTransformIsSensor = true;
......@@ -151,12 +150,10 @@ void GenericRSTransform<TScalarType, NInputDimensions, NOutputDimensions>::Insta
// If not, try to make a RPC sensor model
if ((m_OutputTransform.IsNull()) && (m_OutputImd != nullptr) && (m_OutputImd->Has(MDGeom::RPC)))
{
typedef otb::RPCInverseTransform<double, InputSpaceDimension, OutputSpaceDimension> RPCInverseTransformType;
typename RPCInverseTransformType::Pointer sensorModel = RPCInverseTransformType::New();
sensorModel->SetMetadata(*m_OutputImd);
auto sensorModel = otb::SensorTransformFactory::GetInstance().CreateTransform
<double, InputSpaceDimension, OutputSpaceDimension>(*m_OutputImd,TransformDirection::INVERSE);
if (sensorModel->IsValidSensorModel())
if (sensorModel != nullptr)
{
m_OutputTransform = sensorModel.GetPointer();
outputTransformIsSensor = true;
......
......@@ -33,7 +33,7 @@ namespace otb
*
* \ingroup OTBTransform
*/
template <TransformDirection::TransformationDirection TDirectionOfMapping, class TScalarType = double, unsigned int NInputDimensions = 3,
template <TransformDirection TDirectionOfMapping, class TScalarType = double, unsigned int NInputDimensions = 3,
unsigned int NOutputDimensions = 3>
class ITK_EXPORT GeocentricTransform : public Transform<TScalarType, // Data type for scalars
NInputDimensions, // Number of dimensions in the input space
......@@ -56,7 +56,7 @@ public:
/** Run-time type information (and related methods). */
itkTypeMacro(GeocentricTransform, Transform);
static const TransformDirection::TransformationDirection DirectionOfMapping = TDirectionOfMapping;
static const TransformDirection DirectionOfMapping = TDirectionOfMapping;
itkStaticConstMacro(InputSpaceDimension, unsigned int, NInputDimensions);
itkStaticConstMacro(OutputSpaceDimension, unsigned int, NOutputDimensions);
......
......@@ -26,18 +26,18 @@
namespace otb
{
template <TransformDirection::TransformationDirection TDirectionOfMapping, class TScalarType, unsigned int NInputDimensions, unsigned int NOutputDimensions>
template <TransformDirection TDirectionOfMapping, class TScalarType, unsigned int NInputDimensions, unsigned int NOutputDimensions>
GeocentricTransform<TDirectionOfMapping, TScalarType, NInputDimensions, NOutputDimensions>::GeocentricTransform() : Superclass(ParametersDimension)
{
m_Ellipsoid = EllipsoidAdapter::New();
}
template <TransformDirection::TransformationDirection TDirectionOfMapping, class TScalarType, unsigned int NInputDimensions, unsigned int NOutputDimensions>
template <TransformDirection TDirectionOfMapping, class TScalarType, unsigned int NInputDimensions, unsigned int NOutputDimensions>
GeocentricTransform<TDirectionOfMapping, TScalarType, NInputDimensions, NOutputDimensions>::~GeocentricTransform()
{
}
template <TransformDirection::TransformationDirection TDirectionOfMapping, class TScalarType, unsigned int NInputDimensions, unsigned int NOutputDimensions>
template <TransformDirection TDirectionOfMapping, class TScalarType, unsigned int NInputDimensions, unsigned int NOutputDimensions>
typename GeocentricTransform<TDirectionOfMapping, TScalarType, NInputDimensions, NOutputDimensions>::OutputPointType
GeocentricTransform<TDirectionOfMapping, TScalarType, NInputDimensions, NOutputDimensions>::TransformPoint(const InputPointType& point) const
{
......
......@@ -62,9 +62,10 @@ public:
/** Method to transform a point. */
OutputPointType TransformPoint(const InputPointType& point) const override;
protected:
RPCForwardTransform() = default;
RPCForwardTransform();
~RPCForwardTransform() = default;
protected:
void PrintSelf(std::ostream& os, itk::Indent indent) const override;
private:
......
......@@ -25,6 +25,9 @@
namespace otb
{
template <class TScalarType, unsigned int NInputDimensions, unsigned int NOutputDimensions>
RPCForwardTransform<TScalarType, NInputDimensions, NOutputDimensions>::RPCForwardTransform() : Superclass(TransformDirection::FORWARD)
{}
template <class TScalarType, unsigned int NInputDimensions, unsigned int NOutputDimensions>
typename RPCForwardTransform<TScalarType, NInputDimensions, NOutputDimensions>::OutputPointType
......
......@@ -62,9 +62,10 @@ public:
/** Method to transform a point. */
OutputPointType TransformPoint(const InputPointType& point) const override;
protected:
RPCInverseTransform() = default;
RPCInverseTransform();
~RPCInverseTransform() = default;
protected:
void PrintSelf(std::ostream& os, itk::Indent indent) const override;
private:
......
......@@ -25,6 +25,9 @@
namespace otb
{
template <class TScalarType, unsigned int NInputDimensions, unsigned int NOutputDimensions>
RPCInverseTransform<TScalarType, NInputDimensions, NOutputDimensions>::RPCInverseTransform() : Superclass(TransformDirection::INVERSE)
{}
template <class TScalarType, unsigned int NInputDimensions, unsigned int NOutputDimensions>
typename RPCInverseTransform<TScalarType, NInputDimensions, NOutputDimensions>::OutputPointType
......
......@@ -73,7 +73,7 @@ public:
bool IsValidSensorModel() const override;
protected:
RPCTransformBase() = default;
RPCTransformBase(TransformDirection dir) : Superclass(dir) {};
~RPCTransformBase() = default;
void PrintSelf(std::ostream& os, itk::Indent indent) const override;
......
......@@ -76,10 +76,16 @@ public:
/** Check model validity */
virtual bool IsValidSensorModel() const = 0;
TransformDirection getDirection() const {
return m_direction;
};
protected:
SensorTransformBase() : Superclass(0) {}
SensorTransformBase(TransformDirection dir) : Superclass(0),m_direction(dir) {}
~SensorTransformBase() = default;
TransformDirection m_direction;
private:
SensorTransformBase(const Self&) = delete;
void operator=(const Self&) = delete;
......
/*
* Copyright (C) 2005-2021 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 otbSensorTransformFactory_h
#define otbSensorTransformFactory_h
#include "otbSensorTransformBase.h"
#include "itkMacro.h"
namespace otb
{
/** \class SensorTransformFactory
* \brief Creats an instance of SensorTransform (RPC, SAR ...) object using object factory.
*
* \ingroup OTBTransform
*/
//template <class TScalarType, unsigned int NInputDimensions, unsigned int NOutputDimensions>
class ITK_EXPORT SensorTransformFactory : boost::noncopyable
{
public:
/** Standard class typedefs. */
using Self = SensorTransformFactory;
/** Retrieve the singleton instance */
static SensorTransformFactory & GetInstance();
/** Create the appropriate transform. */
template <class TScalarType, unsigned int NInputDimensions, unsigned int NOutputDimensions>
typename otb::SensorTransformBase<TScalarType, NInputDimensions, NOutputDimensions>::Pointer
CreateTransform(const ImageMetadata &imd, TransformDirection d) const;
private:
SensorTransformFactory() = default;
~SensorTransformFactory() = default;
};
}
#ifndef OTB_MANUAL_INSTANTIATION
#include "otbSensorTransformFactory.hxx"
#endif
#endif // otbSensorTransformFactory_h
/*
* Copyright (C) 2005-2021 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 otbSensorTransformFactory_hxx
#define otbSensorTransformFactory_hxx
#include "otbImageMetadata.h"
#include "otbSensorTransformFactory.h"
#include "otbTransform.h"
#include "otbTransformFactories.h"
#include <functional>
namespace otb
{
template <class TScalarType, unsigned int NInputDimensions, unsigned int NOutputDimensions>
typename otb::SensorTransformBase<TScalarType, NInputDimensions, NOutputDimensions>::Pointer
SensorTransformFactory::CreateTransform(const ImageMetadata &imd, TransformDirection direction) const
{
// Instanciate the factories
std::vector<
std::function<
typename otb::SensorTransformBase<double, NInputDimensions, NOutputDimensions>::Pointer (const ImageMetadata &,
TransformDirection direction)
>
> factories;
factories.push_back(TransformFactories::RPCForwardTransformFactory<TScalarType, NInputDimensions, NOutputDimensions>);
factories.push_back(TransformFactories::RPCInverseTransformFactory<TScalarType, NInputDimensions, NOutputDimensions>);
typename otb::SensorTransformBase<TScalarType, NInputDimensions, NOutputDimensions>::Pointer transformPointer;
for (auto& transformFactory : factories)
{
transformPointer = transformFactory(imd, direction);
if (transformPointer)
{
if (transformPointer->IsValidSensorModel() && transformPointer->getDirection() == direction)
{
return transformPointer;
}
}
}
// if no object has been found, we have to warn the user
otbLogMacro(Warning, << "The SensorTransform factory could not find a compatible Sensor Transform");
return nullptr;
}
} // end namespace otb
#endif
......@@ -27,6 +27,8 @@
namespace otb
{
enum class TransformDirection {FORWARD,INVERSE};
/** \class Transform
* \brief Class to overload method passed to virtual pure in ITK V4.
*
......
/*
* 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 otbTransformFactory_h
#define otbTransformFactory_h
#include "otbCast.h"
#include "otbImageMetadata.h"
#include "otbSensorTransformBase.h"
#include "otbTransform.h"
#include "otbRPCForwardTransform.h"
#include "otbRPCInverseTransform.h"
namespace otb {
/** \namespace TransformFactories
* \brief Contains the functions (factories) used to instanciate the transformation classes.
*
* Each function is in charge of instanciating a specific transformation classes. It is
* templated with the scalar type used in the Sensor Model, the dimension of the
* inpute space, and the dimension of the output space. It takes as parameter a
* reference to the ImageMetadata object used to instanciate the Sensor Model, and the
* TransformDirection. It returns an instance of otb::SensorTransformBase.
*
* \ingroup OTBTransform
*/
namespace TransformFactories {
/**
* Factory for the forward transformer based of the RPC sensor model
*/
template <class TScalarType, unsigned int NInputDimensions, unsigned int NOutputDimensions>
typename otb::SensorTransformBase<double, NInputDimensions, NOutputDimensions>::Pointer
RPCForwardTransformFactory(const ImageMetadata &imd, TransformDirection direction)
{
if(imd.Has(MDGeom::RPC))
{
auto transform = RPCForwardTransform<TScalarType, NInputDimensions,NOutputDimensions>::New();
if(transform->getDirection() != direction)
return nullptr;
transform->SetMetadata(imd);
return DynamicCast<typename otb::SensorTransformBase<double, NInputDimensions, NOutputDimensions>>(transform);
}
return nullptr;
}
/**
* Factory for the inverse transformer based of the RPC sensor model
*/
template <class TScalarType, unsigned int NInputDimensions, unsigned int NOutputDimensions>
typename otb::SensorTransformBase<double, NInputDimensions, NOutputDimensions>::Pointer
RPCInverseTransformFactory(const ImageMetadata &imd, TransformDirection direction)
{
if(imd.Has(MDGeom::RPC))
{
auto transform = RPCInverseTransform<TScalarType, NInputDimensions,NOutputDimensions>::New();
if(transform->getDirection() != direction)
return nullptr;
transform->SetMetadata(imd);
return DynamicCast<typename otb::SensorTransformBase<double, NInputDimensions, NOutputDimensions>>(transform);
}
return nullptr;
}
}
}
#endif
......@@ -22,6 +22,7 @@ set(OTBTransform_SRC
otbSensorModelAdapter.cxx
otbSarSensorModel.cxx
otbSarSensorModelAdapter.cxx
otbSensorTransformFactory.cxx
)
add_library(OTBTransform ${OTBTransform_SRC})
......
/*
* 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 "otbSensorTransformFactory.h"
namespace otb {
// Meyer singleton design pattern
SensorTransformFactory & SensorTransformFactory::GetInstance()
{
static SensorTransformFactory s_instance;
return s_instance;
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment