From f6a936f98d6364fdb1469788fff72edbbab8add8 Mon Sep 17 00:00:00 2001
From: Julien Michel <julien.michel@orfeo-toolbox.org>
Date: Tue, 8 Jul 2014 16:28:06 +0200
Subject: [PATCH] ENH: Removing duplicated code, replacing by helper class

---
 Applications/Projections/CMakeLists.txt       |  14 +-
 .../Projections/otbBundleToPerfectSensor.cxx  | 143 ++----------------
 Applications/Projections/otbSuperimpose.cxx   | 139 ++---------------
 3 files changed, 34 insertions(+), 262 deletions(-)

diff --git a/Applications/Projections/CMakeLists.txt b/Applications/Projections/CMakeLists.txt
index 4323e63f84..d13b0c1608 100644
--- a/Applications/Projections/CMakeLists.txt
+++ b/Applications/Projections/CMakeLists.txt
@@ -1,11 +1,11 @@
 
 OTB_CREATE_APPLICATION(NAME           BundleToPerfectSensor
                        SOURCES        otbBundleToPerfectSensor.cxx
-                       LINK_LIBRARIES OTBBasicFilters)
+                       LINK_LIBRARIES OTBBasicFilters;OTBProjections)
 
 OTB_CREATE_APPLICATION(NAME           OrthoRectification
                        SOURCES        otbOrthoRectification.cxx
-                       LINK_LIBRARIES OTBBasicFilters)
+                       LINK_LIBRARIES OTBBasicFilters;OTBProjections)
 
 OTB_CREATE_APPLICATION(NAME           RigidTransformResample
                        SOURCES        otbRigidTransformResample.cxx
@@ -13,23 +13,23 @@ OTB_CREATE_APPLICATION(NAME           RigidTransformResample
 
 OTB_CREATE_APPLICATION(NAME           Superimpose
                        SOURCES        otbSuperimpose.cxx
-                       LINK_LIBRARIES OTBBasicFilters)
+                       LINK_LIBRARIES OTBBasicFilters;OTBProjections)
 
 OTB_CREATE_APPLICATION(NAME           ConvertCartoToGeoPoint
                        SOURCES        otbConvertCartoToGeoPoint.cxx
-                       LINK_LIBRARIES OTBBasicFilters)
+                       LINK_LIBRARIES OTBBasicFilters;OTBProjections)
 
 OTB_CREATE_APPLICATION(NAME           ImageEnvelope
                        SOURCES        otbImageEnvelope.cxx
-                       LINK_LIBRARIES OTBBasicFilters)
+                       LINK_LIBRARIES OTBBasicFilters;OTBProjections)
 
 OTB_CREATE_APPLICATION(NAME           ObtainUTMZoneFromGeoPoint
                        SOURCES        otbObtainUTMZoneFromGeoPoint.cxx
-                       LINK_LIBRARIES OTBBasicFilters)
+                       LINK_LIBRARIES OTBBasicFilters;OTBProjections)
 
 OTB_CREATE_APPLICATION(NAME           ConvertSensorToGeoPoint
                        SOURCES        otbConvertSensorToGeoPoint.cxx
-                       LINK_LIBRARIES OTBBasicFilters)
+                       LINK_LIBRARIES OTBBasicFilters;OTBProjections)
 
 OTB_CREATE_APPLICATION(NAME           GridBasedImageResampling
                        SOURCES        otbGridBasedImageResampling.cxx
diff --git a/Applications/Projections/otbBundleToPerfectSensor.cxx b/Applications/Projections/otbBundleToPerfectSensor.cxx
index 3bbe1712c1..f1140a59e4 100644
--- a/Applications/Projections/otbBundleToPerfectSensor.cxx
+++ b/Applications/Projections/otbBundleToPerfectSensor.cxx
@@ -23,26 +23,17 @@
 #include "otbBCOInterpolateImageFunction.h"
 #include "otbSimpleRcsPanSharpeningFusionImageFilter.h"
 #include "itkFixedArray.h"
-#include "itkScalableAffineTransform.h"
 
 // Elevation handler
 #include "otbWrapperElevationParametersHandler.h"
 
-#include "otbDateTimeAdapter.h"
 #include "otbStreamingResampleImageFilter.h"
-#include "otbPleiadesImageMetadataInterface.h"
+#include "otbPleiadesPToXSAffineTransformCalculator.h"
 
 namespace otb
 {
 namespace Wrapper
 {
-
-enum
-{
-  Mode_Default,
-  Mode_PHR
-};
-
 class BundleToPerfectSensor : public Application
 {
 public:
@@ -113,49 +104,10 @@ private:
 
   void DoUpdateParameters()
   {
-    if (!HasUserValue("mode") &&
-        GetParameterInt("mode") == Mode_Default &&
-        HasValue("inp") &&
-        HasValue("inxs"))
+    if(HasValue("inp") && HasValue("inxs") && otb::PleiadesPToXSAffineTransformCalculator::CanCompute(GetParameterImage("inp"),GetParameterImage("inxs")))
       {
-      FloatVectorImageType* refImage = GetParameterImage("inp");
-      FloatVectorImageType* movingImage = GetParameterImage("inxs");
-      bool isRefPHR = false;
-      bool isMovingPHR = false;
-      
-      otb::PleiadesImageMetadataInterface::Pointer phrIMI =
-        otb::PleiadesImageMetadataInterface::New();
-      phrIMI->SetMetaDataDictionary(refImage->GetMetaDataDictionary());
-      isRefPHR = phrIMI->CanRead();
-      
-      phrIMI->SetMetaDataDictionary(movingImage->GetMetaDataDictionary());
-      isMovingPHR = phrIMI->CanRead();
-      
-      if (isRefPHR && isMovingPHR)
-        {
-        ImageKeywordlist kwlPan;
-        ImageKeywordlist kwlXS;
-        
-        itk::ExposeMetaData<ImageKeywordlist>(
-          refImage->GetMetaDataDictionary(),
-          MetaDataKey::OSSIMKeywordlistKey,
-          kwlPan);
-        
-        itk::ExposeMetaData<ImageKeywordlist>(
-          movingImage->GetMetaDataDictionary(),
-          MetaDataKey::OSSIMKeywordlistKey,
-          kwlXS);
-        
-        // Get geometric processing
-        std::string panProcessing = kwlPan.GetMetadataByKey("support_data.processing_level");
-        std::string xsProcessing = kwlXS.GetMetadataByKey("support_data.processing_level");
-        
-        if (panProcessing.compare("SENSOR") == 0 &&
-            xsProcessing.compare("SENSOR") == 0)
-          {
-          SetParameterInt("mode",Mode_PHR);
-          }
-        }
+      otbAppLogWARNING("Forcing PHR mode with PHR data. You need to add \"-mode default\" to force the default mode with PHR images.");
+      SetParameterString("mode","phr");
       }
   }
 
@@ -180,9 +132,6 @@ private:
     channelSelect->UpdateOutputInformation();
     FloatImageType::Pointer panchro = channelSelect->GetOutput();
 
-
-   
-
     typedef otb::BCOInterpolateImageFunction<FloatVectorImageType> InterpolatorType;
     typedef otb::GenericRSResampleImageFilter<FloatVectorImageType, FloatVectorImageType>  ResamplerType;
     typedef otb::StreamingResampleImageFilter<FloatVectorImageType, FloatVectorImageType>  BasicResamplerType;
@@ -216,9 +165,7 @@ private:
     FloatVectorImageType::PixelType defaultValue;
     itk::NumericTraits<FloatVectorImageType::PixelType>::SetLength(defaultValue, xs->GetNumberOfComponentsPerPixel());
 
-    switch ( GetParameterInt("mode") )
-    {
-    case Mode_Default:
+    if(GetParameterString("mode") == "default")
       {
       otbAppLogINFO("Using the default mode");
       if(IsParameterEnabled("lms") && HasValue("lms"))
@@ -226,10 +173,10 @@ private:
         double defScalarSpacing = GetParameterFloat("lms");
         otbAppLogINFO(<< "Generating coarse deformation field (spacing="<<defScalarSpacing<<")" << std::endl);
         FloatVectorImageType::SpacingType defSpacing;
-
+        
         defSpacing[0] = defScalarSpacing;
         defSpacing[1] = defScalarSpacing;
-
+        
         resampler->SetDisplacementFieldSpacing(defSpacing);
         }
       else
@@ -248,78 +195,17 @@ private:
       resampler->SetOutputKeywordList(panchro->GetImageKeywordlist());
       resampler->SetOutputProjectionRef(panchro->GetProjectionRef());
       resampler->SetEdgePaddingValue(defaultValue);
-      //resampler->UpdateOutputInformation();
-      // TODO : set the Input keywordlist and ProjRef manually ??
       fusionFilter->SetXsInput(resampler->GetOutput());
-      //fusionFilter->UpdateOutputInformation();
       }
-      break;
-    case Mode_PHR:
+    else if(GetParameterString("mode")=="phr")
       {
       otbAppLogINFO("Using the PHR mode");
-      // Setup a simple affine transform using PHR support data
-      ImageKeywordlist kwlPan;
-      ImageKeywordlist kwlXS;
-      
-      itk::ExposeMetaData<ImageKeywordlist>(
-        panchroV->GetMetaDataDictionary(),
-        MetaDataKey::OSSIMKeywordlistKey,
-        kwlPan);
-      
-      itk::ExposeMetaData<ImageKeywordlist>(
-        xs->GetMetaDataDictionary(),
-        MetaDataKey::OSSIMKeywordlistKey,
-        kwlXS);
-      
-      // Compute time delta
-      std::string strStartTimePan = kwlPan.GetMetadataByKey("support_data.time_range_start");
-      std::string strStartTimeXS = kwlXS.GetMetadataByKey("support_data.time_range_start");
-      
-      DateTimeAdapter::Pointer startTimePan = DateTimeAdapter::New();
-      DateTimeAdapter::Pointer startTimeXS = DateTimeAdapter::New();
-      
-      startTimePan->SetFromIso8601(strStartTimePan);
-      startTimeXS->SetFromIso8601(strStartTimeXS);
-      
-      double timeDelta = startTimeXS->GetDeltaInSeconds(startTimePan);
-      
-      // Retrieve line period in Pan
-      std::string tmpStr = kwlPan.GetMetadataByKey("support_data.line_period");
-      double linePeriodPan = atof(tmpStr.c_str());
-      
-      // Retrieve column start
-      tmpStr = kwlPan.GetMetadataByKey("support_data.swath_first_col");
-      int colStartPan = atoi(tmpStr.c_str());
-      tmpStr = kwlXS.GetMetadataByKey("support_data.swath_first_col");
-      int colStartXS = atoi(tmpStr.c_str());
-      
-      // Compute shift between MS and P (in Pan pixels)
-      int lineShift_MS_P =int(vcl_floor((timeDelta/(linePeriodPan/1000))  + 0.5))+0.375;
-      int colShift_MS_P = colStartXS*4 - colStartPan-4+0.375;
-      
-      // Apply the scaling
-      typedef itk::ScalableAffineTransform<double, 2>  TransformType;
-      TransformType::Pointer transform = TransformType::New();
-      transform->Scale(4.0);
-      
-      // Resample filter assumes the origin is attached to the pixel center
-      // in order to keep the top left corners unchanged, apply a -(3/2) pixels
-      // shift in each direction
-      // TODO : clarify formula
-      TransformType::OutputVectorType offset;
-      offset[0] = static_cast<double>(colShift_MS_P);
-      offset[1] = static_cast<double>(lineShift_MS_P);
-      transform->Translate(offset);
-
-      otbAppLogINFO(<< "Offset computed between MS and P (in Pan pixels) in PHR mode= "<< offset << std::endl);
-      
-      // Invert the transform as the resampler filter expect an output-to-input
-      // transform (we have computed the input-to-output transform)
-      TransformType::Pointer realTransform = TransformType::New();
-      transform->GetInverse(realTransform);
-      basicResampler->SetTransform(realTransform);
       
+      otb::PleiadesPToXSAffineTransformCalculator::TransformType::Pointer transform
+        = otb::PleiadesPToXSAffineTransformCalculator::Compute(panchro, xs);
+
       basicResampler->SetInput(xs);
+      basicResampler->SetTransform(transform);
       basicResampler->SetOutputOrigin(origin);
       basicResampler->SetOutputSpacing(spacing);
       basicResampler->SetOutputSize(size);
@@ -336,13 +222,10 @@ private:
       itk::EncapsulateMetaData<ImageKeywordlist>(dict, MetaDataKey::OSSIMKeywordlistKey,
                                                  panchro->GetImageKeywordlist());
       }
-      break;
-    default:
+    else
       {
       otbAppLogWARNING("Unknown mode");
       }
-      break;
-    }
     
     SetParameterOutputImage("out", fusionFilter->GetOutput());
   }
diff --git a/Applications/Projections/otbSuperimpose.cxx b/Applications/Projections/otbSuperimpose.cxx
index 32e5f8a76c..15fe9cff34 100644
--- a/Applications/Projections/otbSuperimpose.cxx
+++ b/Applications/Projections/otbSuperimpose.cxx
@@ -24,15 +24,10 @@
 #include "otbBCOInterpolateImageFunction.h"
 #include "itkNearestNeighborInterpolateImageFunction.h"
 
-#include "otbPleiadesImageMetadataInterface.h"
-
-#include "itkScalableAffineTransform.h"
-
 // Elevation handler
 #include "otbWrapperElevationParametersHandler.h"
-
-#include "otbDateTimeAdapter.h"
 #include "otbStreamingResampleImageFilter.h"
+#include "otbPleiadesPToXSAffineTransformCalculator.h"
 
 namespace otb
 {
@@ -44,12 +39,6 @@ enum
   Interpolator_Linear
 };
 
-enum
-{
-  Mode_Default,
-  Mode_PHR
-};
-
 namespace Wrapper
 {
 
@@ -160,49 +149,10 @@ private:
 
   void DoUpdateParameters()
   {
-    if (!HasUserValue("mode") &&
-        GetParameterInt("mode") == Mode_Default &&
-        HasValue("inr") &&
-        HasValue("inm"))
+    if(HasValue("inr") && HasValue("inm") && otb::PleiadesPToXSAffineTransformCalculator::CanCompute(GetParameterImage("inr"),GetParameterImage("inm")))
       {
-      FloatVectorImageType* refImage = GetParameterImage("inr");
-      FloatVectorImageType* movingImage = GetParameterImage("inm");
-      bool isRefPHR = false;
-      bool isMovingPHR = false;
-      
-      otb::PleiadesImageMetadataInterface::Pointer phrIMI =
-        otb::PleiadesImageMetadataInterface::New();
-      phrIMI->SetMetaDataDictionary(refImage->GetMetaDataDictionary());
-      isRefPHR = phrIMI->CanRead();
-      
-      phrIMI->SetMetaDataDictionary(movingImage->GetMetaDataDictionary());
-      isMovingPHR = phrIMI->CanRead();
-      
-      if (isRefPHR && isMovingPHR)
-        {
-        ImageKeywordlist kwlPan;
-        ImageKeywordlist kwlXS;
-        
-        itk::ExposeMetaData<ImageKeywordlist>(
-          refImage->GetMetaDataDictionary(),
-          MetaDataKey::OSSIMKeywordlistKey,
-          kwlPan);
-        
-        itk::ExposeMetaData<ImageKeywordlist>(
-          movingImage->GetMetaDataDictionary(),
-          MetaDataKey::OSSIMKeywordlistKey,
-          kwlXS);
-        
-        // Get geometric processing
-        std::string panProcessing = kwlPan.GetMetadataByKey("support_data.processing_level");
-        std::string xsProcessing = kwlXS.GetMetadataByKey("support_data.processing_level");
-        
-        if (panProcessing.compare("SENSOR") == 0 &&
-            xsProcessing.compare("SENSOR") == 0)
-          {
-          SetParameterInt("mode",Mode_PHR);
-          }
-        }
+      otbAppLogWARNING("Forcing PHR mode with PHR data. You need to add \"-mode default\" to force the default mode with PHR images.");
+      SetParameterString("mode","phr");
       }
   }
 
@@ -257,10 +207,9 @@ private:
     
     FloatVectorImageType::PixelType defaultValue;
     itk::NumericTraits<FloatVectorImageType::PixelType>::SetLength(defaultValue, movingImage->GetNumberOfComponentsPerPixel());
+
     
-    switch ( GetParameterInt("mode") )
-    {
-    case Mode_Default:
+    if(GetParameterString("mode")=="default")
       {
       if(IsParameterEnabled("lms"))
         {
@@ -296,68 +245,15 @@ private:
       // Set the output image
       SetParameterOutputImage("out", m_Resampler->GetOutput());
       }
-      break;
-    case Mode_PHR:
+    else if(GetParameterString("mode")=="phr")
       {
       otbAppLogINFO("Using the PHR mode");
       
-      // Setup a simple affine transform using PHR support data
-      ImageKeywordlist kwlPan;
-      ImageKeywordlist kwlXS;
-      
-      itk::ExposeMetaData<ImageKeywordlist>(
-        refImage->GetMetaDataDictionary(),
-        MetaDataKey::OSSIMKeywordlistKey,
-        kwlPan);
-      
-      itk::ExposeMetaData<ImageKeywordlist>(
-        movingImage->GetMetaDataDictionary(),
-        MetaDataKey::OSSIMKeywordlistKey,
-        kwlXS);
-      
-      // Compute time delta
-      std::string strStartTimePan = kwlPan.GetMetadataByKey("support_data.time_range_start");
-      std::string strStartTimeXS = kwlXS.GetMetadataByKey("support_data.time_range_start");
-      
-      DateTimeAdapter::Pointer startTimePan = DateTimeAdapter::New();
-      DateTimeAdapter::Pointer startTimeXS = DateTimeAdapter::New();
-      
-      startTimePan->SetFromIso8601(strStartTimePan);
-      startTimeXS->SetFromIso8601(strStartTimeXS);
-      
-      double timeDelta = startTimeXS->GetDeltaInSeconds(startTimePan);
-      
-      // Retrieve line period in Pan
-      std::string tmpStr = kwlPan.GetMetadataByKey("support_data.line_period");
-      double linePeriodPan = atof(tmpStr.c_str());
-      
-      // Retrieve column start
-      tmpStr = kwlPan.GetMetadataByKey("support_data.swath_first_col");
-      int colStartPan = atoi(tmpStr.c_str());
-      tmpStr = kwlXS.GetMetadataByKey("support_data.swath_first_col");
-      int colStartXS = atoi(tmpStr.c_str());
-      
-      // Compute shift between MS and P (in Pan pixels)
-      int lineShift_MS_P =int(vcl_floor((timeDelta/(linePeriodPan/1000))  + 0.5)) + 0.375;
-      int colShift_MS_P = colStartXS*4 - colStartPan - 4 + 0.375;
-      
-      // Apply the scaling
-      TransformType::Pointer transform = TransformType::New();
-      transform->Scale(4.0);
-      
-      // Resample filter assumes the origin is attached to the pixel center
-      // in order to keep the top left corners unchanged, apply a 3/2 pixels
-      // shift in each direction
-      TransformType::OutputVectorType offset;
-      offset[0] = 1.5 + static_cast<double>(colShift_MS_P);
-      offset[1] = 1.5 + static_cast<double>(lineShift_MS_P);
-      transform->Translate(offset);
-      
-      // Invert the transform as the resampler filter expect an output-to-input
-      // transform (we have computed the input-to-output transform)
-      TransformType::Pointer realTransform = TransformType::New();
-      transform->GetInverse(realTransform);
-      m_BasicResampler->SetTransform(realTransform);
+      otb::PleiadesPToXSAffineTransformCalculator::TransformType::Pointer transform
+        = otb::PleiadesPToXSAffineTransformCalculator::Compute(GetParameterImage("inr"),
+                                                               GetParameterImage("inm"));
+
+      m_BasicResampler->SetTransform(transform);
       
       m_BasicResampler->SetInput(movingImage);
       
@@ -370,20 +266,13 @@ private:
 
       // Set the output image
       SetParameterOutputImage("out", m_BasicResampler->GetOutput());
-      
-      otbAppLogINFO("Line shift (in pix)  : "<< lineShift_MS_P);
-      otbAppLogINFO("Col shift (in pix)   : "<< colShift_MS_P);
       }
-      break;
-    default:
+    else
       {
       otbAppLogWARNING("Unknown mode");
       }
-      break;
-    }
-   
   }
-
+   
   ResamplerType::Pointer           m_Resampler;
   
   BasicResamplerType::Pointer      m_BasicResampler;
-- 
GitLab