From c2c8aab321e7d876f9b70c3ff9b81ff543e6ab3a Mon Sep 17 00:00:00 2001
From: Aurelien Bricier <aurelien.bricier@c-s.fr>
Date: Mon, 8 Nov 2010 17:18:35 +0100
Subject: [PATCH] ENH: added VariableLengthVectorConverter

---
 .../Common/otbVariableLengthVectorConverter.h | 258 ++++++++++++++++++
 .../otbVariableLengthVectorConverter.txx      | 133 +++++++++
 Testing/Code/Common/CMakeLists.txt            |  11 +-
 Testing/Code/Common/otbCommonTests12.cxx      |   2 +
 .../otbVariableLengthVectorConverter.cxx      |  54 ++++
 5 files changed, 457 insertions(+), 1 deletion(-)
 create mode 100644 Code/Common/otbVariableLengthVectorConverter.h
 create mode 100644 Code/Common/otbVariableLengthVectorConverter.txx
 create mode 100644 Testing/Code/Common/otbVariableLengthVectorConverter.cxx

diff --git a/Code/Common/otbVariableLengthVectorConverter.h b/Code/Common/otbVariableLengthVectorConverter.h
new file mode 100644
index 0000000000..fac00cf55e
--- /dev/null
+++ b/Code/Common/otbVariableLengthVectorConverter.h
@@ -0,0 +1,258 @@
+/*=========================================================================
+
+  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.
+
+=========================================================================*/
+#ifndef __otbVariableLengthVectorConverter_h
+#define __otbVariableLengthVectorConverter_h
+
+#include "itkProcessObject.h"
+#include "itkVariableLengthVector.h"
+#include "itkNumericTraits.h"
+#include "itkExceptionObject.h"
+#include "itkFixedArray.h"
+#include "itkHistogram.h"
+
+
+namespace otb
+{
+/**
+ * \class VariableLengthVectorConverter
+ * \brief Convert any data container type into a VariableLengthVector.
+ *
+ * To be usable, the desired convertion must be implemented through
+ * partial specialisation mecanism.
+ * 
+ */
+
+//Base
+template< class TInputType, class TPrecisionType = double >
+class ITK_EXPORT VariableLengthVectorConverter :
+public itk::ProcessObject
+{
+public:
+  /** Standard class typedefs */
+  typedef VariableLengthVectorConverter                Self;
+  typedef itk::ProcessObject                           Superclass;
+  typedef itk::SmartPointer<Self>                      Pointer;
+  typedef itk::SmartPointer<const Self>                ConstPointer;
+ 
+  /** Run-time type information (and related methods). */
+  itkTypeMacro(VariableLengthVectorConverter, ProcessObject);
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self); 
+
+  typedef TPrecisionType                                            OutputPrecisionType;
+  typedef typename itk::VariableLengthVector<OutputPrecisionType>   OutputType;
+  typedef TInputType                                                InputType;
+  
+  OutputType Convert (InputType input)
+  {
+    itkGenericExceptionMacro( << "Type Convertion Not Implemented." << std::endl );
+  }
+
+protected:
+  VariableLengthVectorConverter(){}
+  virtual ~VariableLengthVectorConverter(){}
+  virtual void PrintSelf(std::ostream& os, itk::Indent indent) const
+  {
+    Superclass::PrintSelf(os, indent);
+    os << "Attempt to use inexistant implementation of the converter!" 
+       << std::endl;
+  }
+
+private:
+  VariableLengthVectorConverter(const Self&); //purposely not implemented
+  void operator=(const Self&); //purposely not implemented
+};
+
+
+
+// Real Matrix
+template< class TInternalInputType, class TPrecisionType >
+class ITK_EXPORT VariableLengthVectorConverter<std::vector<std::vector<TInternalInputType> >,
+                                               TPrecisionType> :
+public itk::ProcessObject
+{
+public:
+  /** Standard class typedefs */
+  typedef VariableLengthVectorConverter                Self;
+  typedef itk::ProcessObject                           Superclass;
+  typedef itk::SmartPointer<Self>                      Pointer;
+  typedef itk::SmartPointer<const Self>                ConstPointer;
+ 
+  /** Run-time type information (and related methods). */
+  itkTypeMacro(VariableLengthVectorConverter, ProcessObject);
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self); 
+
+  typedef TPrecisionType                                            OutputPrecisionType;
+  typedef typename itk::VariableLengthVector<OutputPrecisionType>   OutputType;
+  typedef typename std::vector<std::vector<TInternalInputType> >    InputType;
+
+  OutputType Convert(InputType input);
+
+protected:
+  VariableLengthVectorConverter(){}
+  virtual ~VariableLengthVectorConverter(){}
+  virtual void PrintSelf(std::ostream& os, itk::Indent indent) const
+  {
+    Superclass::PrintSelf(os, indent);
+    os << "Converter: std::vector<std::vector<RealType>>  => VariableLengthVector<RealType>" 
+       << std::endl;
+  }
+
+private:
+  VariableLengthVectorConverter(const Self&); //purposely not implemented
+  void operator=(const Self&); //purposely not implemented
+};
+
+
+
+//Complex Matrix
+template< class TInternalInputType, class TPrecisionType >
+class ITK_EXPORT VariableLengthVectorConverter<std::vector<std::vector<std::complex<TInternalInputType> > >,
+                                               TPrecisionType> :
+public itk::ProcessObject
+{
+public:
+  /** Standard class typedefs */
+  typedef VariableLengthVectorConverter                Self;
+  typedef itk::ProcessObject                           Superclass;
+  typedef itk::SmartPointer<Self>                      Pointer;
+  typedef itk::SmartPointer<const Self>                ConstPointer;
+ 
+  /** Run-time type information (and related methods). */
+  itkTypeMacro(VariableLengthVectorConverter, ProcessObject);
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self); 
+
+  typedef TPrecisionType                                                           OutputPrecisionType;
+  typedef typename itk::VariableLengthVector<OutputPrecisionType>                  OutputType;
+  typedef typename std::vector<std::vector<std::complex<TInternalInputType> > >    InputType;
+
+  OutputType Convert(InputType input);
+
+protected:
+  VariableLengthVectorConverter(){}
+  virtual ~VariableLengthVectorConverter(){}
+  virtual void PrintSelf(std::ostream& os, itk::Indent indent) const
+  {
+    Superclass::PrintSelf(os, indent);
+    os << "Converter: std::vector<std::vector<std::complex<RealType>>>  => VariableLengthVector<RealType>" 
+       << std::endl;
+  }
+
+private:
+  VariableLengthVectorConverter(const Self&); //purposely not implemented
+  void operator=(const Self&); //purposely not implemented
+};
+
+
+
+//Fixed Array
+template< class TInternalInputType, unsigned int VArrayDimension, class TPrecisionType >
+class ITK_EXPORT VariableLengthVectorConverter<itk::FixedArray<TInternalInputType, VArrayDimension>,
+                                               TPrecisionType> :
+public itk::ProcessObject
+{
+public:
+  /** Standard class typedefs */
+  typedef VariableLengthVectorConverter                Self;
+  typedef itk::ProcessObject                           Superclass;
+  typedef itk::SmartPointer<Self>                      Pointer;
+  typedef itk::SmartPointer<const Self>                ConstPointer;
+ 
+  /** Run-time type information (and related methods). */
+  itkTypeMacro(VariableLengthVectorConverter, ProcessObject);
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self); 
+
+  typedef TPrecisionType                                                           OutputPrecisionType;
+  typedef typename itk::VariableLengthVector<OutputPrecisionType>                  OutputType;
+  typedef typename itk::FixedArray<TInternalInputType, VArrayDimension>            InputType;
+
+  OutputType Convert(InputType input);
+ 
+protected:
+  VariableLengthVectorConverter(){}
+  virtual ~VariableLengthVectorConverter(){}
+  virtual void PrintSelf(std::ostream& os, itk::Indent indent) const
+  {
+    Superclass::PrintSelf(os, indent);
+    os << "Converter: itk::FixedArray<RealType, VArrayDimension>  => VariableLengthVector<RealType>" 
+       << std::endl;
+  }
+
+private:
+  VariableLengthVectorConverter(const Self&); //purposely not implemented
+  void operator=(const Self&); //purposely not implemented
+};
+
+//Histogram
+template< class TMeasurement, unsigned int VMeasurementVectorSize, class TFrequencyContainer, class TPrecisionType >
+class ITK_EXPORT VariableLengthVectorConverter<itk::Statistics::Histogram<TMeasurement, 
+                                                                          VMeasurementVectorSize, 
+                                                                          TFrequencyContainer>,
+                                               TPrecisionType> :
+public itk::ProcessObject
+{
+public:
+  /** Standard class typedefs */
+  typedef VariableLengthVectorConverter                Self;
+  typedef itk::ProcessObject                           Superclass;
+  typedef itk::SmartPointer<Self>                      Pointer;
+  typedef itk::SmartPointer<const Self>                ConstPointer;
+ 
+  /** Run-time type information (and related methods). */
+  itkTypeMacro(VariableLengthVectorConverter, ProcessObject);
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self); 
+
+  typedef TPrecisionType                                                           OutputPrecisionType;
+  typedef typename itk::VariableLengthVector<OutputPrecisionType>                  OutputType;
+  typedef typename itk::Statistics::Histogram<TMeasurement, 
+                                              VMeasurementVectorSize, 
+                                              TFrequencyContainer>                 InputType;
+
+  OutputType Convert(InputType input);
+ 
+protected:
+  VariableLengthVectorConverter(){}
+  virtual ~VariableLengthVectorConverter(){}
+  virtual void PrintSelf(std::ostream& os, itk::Indent indent) const
+  {
+    Superclass::PrintSelf(os, indent);
+    os << "Converter: itk::Statistics::Histogram<RealType, VMeasurementVectorSize, TFrequencyContainer>  => VariableLengthVector<RealType>" 
+       << std::endl;
+  }
+
+private:
+  VariableLengthVectorConverter(const Self&); //purposely not implemented
+  void operator=(const Self&); //purposely not implemented
+};
+
+}// namespace otb
+
+#ifndef OTB_MANUAL_INSTANTIATION
+#include "otbVariableLengthVectorConverter.txx"
+#endif
+
+#endif
diff --git a/Code/Common/otbVariableLengthVectorConverter.txx b/Code/Common/otbVariableLengthVectorConverter.txx
new file mode 100644
index 0000000000..16a84fd82a
--- /dev/null
+++ b/Code/Common/otbVariableLengthVectorConverter.txx
@@ -0,0 +1,133 @@
+/*=========================================================================
+
+  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.
+
+=========================================================================*/
+#ifndef __otbVariableLengthVectorConverter_txx
+#define __otbVariableLengthVectorConverter_txx
+
+#include "otbVariableLengthVectorConverter.h"
+#include "itkNumericTraits.h"
+#include <complex>
+
+
+namespace otb
+{
+
+// Real Matrix
+template< class TInternalInputType, class TPrecisionType >
+typename VariableLengthVectorConverter< std::vector<std::vector<TInternalInputType> >, TPrecisionType>
+::OutputType
+VariableLengthVectorConverter< std::vector<std::vector<TInternalInputType> >, TPrecisionType>
+::Convert(InputType input)
+{
+  unsigned int p, q, rsltIdx = 0;
+  OutputType result;
+  
+  p = input.size();
+  q = input.at(0).size();
+
+  result.SetSize(p*q);
+
+  for (unsigned int i=0; i<p; i++)
+    {
+    for (unsigned int j=0; j<q; j++)
+      {
+      result[rsltIdx] = static_cast<OutputPrecisionType>(input.at(i).at(j));
+      rsltIdx ++;
+      }
+    }
+  
+  return result;
+}
+
+// Complex Matrix
+template< class TInternalInputType, class TPrecisionType >
+typename VariableLengthVectorConverter< std::vector<std::vector<std::complex<TInternalInputType> > >,
+                                        TPrecisionType>
+::OutputType
+VariableLengthVectorConverter< std::vector<std::vector<std::complex<TInternalInputType> > >, 
+                               TPrecisionType>
+::Convert(InputType input)
+{
+  unsigned int p, q, rsltIdx = 0;
+  OutputType result;
+  
+  p = input.size();
+  q = input.at(0).size();
+
+  result.SetSize(p*q*2);
+
+  for (unsigned int i=0; i<p; i++)
+    {
+    for (unsigned int j=0; j<q; j++)
+      {
+      result[rsltIdx] = static_cast<OutputPrecisionType>(input.at(i).at(j).real());
+      rsltIdx ++;
+      result[rsltIdx] = static_cast<OutputPrecisionType>(input.at(i).at(j).imag());
+      rsltIdx ++;
+      }
+    }
+  
+  return result;
+}
+
+// Fixed Array
+template< class TInternalInputType, unsigned int VArrayDimension, class TPrecisionType >
+typename VariableLengthVectorConverter< itk::FixedArray<TInternalInputType, VArrayDimension>, TPrecisionType>
+::OutputType
+VariableLengthVectorConverter< itk::FixedArray<TInternalInputType, VArrayDimension>, TPrecisionType>
+::Convert(InputType input)
+{
+  unsigned int p, q, rsltIdx = 0;
+  OutputType result;
+
+  result.SetSize(VArrayDimension);
+
+  for (unsigned int i=0; i<VArrayDimension; i++)
+    {
+    result[rsltIdx] = static_cast<OutputPrecisionType>(input[i]);
+    rsltIdx ++;
+    }
+  
+  return result;
+}
+
+// Histogram
+template< class TMeasurement, unsigned int VMeasurementVectorSize, class TFrequencyContainer, class TPrecisionType >
+typename VariableLengthVectorConverter< itk::Statistics::Histogram<TMeasurement, VMeasurementVectorSize, TFrequencyContainer>, TPrecisionType>
+::OutputType
+VariableLengthVectorConverter< itk::Statistics::Histogram<TMeasurement, VMeasurementVectorSize, TFrequencyContainer>, TPrecisionType>
+::Convert(InputType input)
+{
+  unsigned int nbBins, rsltIdx = 0;
+  OutputType result;
+
+  nbBins = input.GetSize();
+
+  result.SetSize(nbBins);
+
+  for (unsigned int i=0; i<nbBins; i++)
+    {
+    result[rsltIdx] = static_cast<OutputPrecisionType>(input.GetFrequency(i));
+    rsltIdx ++;
+    }
+  
+  return result;
+}
+
+} // namespace otb
+
+#endif
diff --git a/Testing/Code/Common/CMakeLists.txt b/Testing/Code/Common/CMakeLists.txt
index f5ba7d62e4..9630fc3714 100644
--- a/Testing/Code/Common/CMakeLists.txt
+++ b/Testing/Code/Common/CMakeLists.txt
@@ -919,7 +919,7 @@ otbUnaryFunctorWithIndexImageFilter
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ otbCommonTests12 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-# ----------------  otbParser  ---------------------#
+# ----------------  otbParser  --------------------- #
   ADD_TEST(coTuParser ${COMMON_TESTS12}
     otbParserTestNew
     )
@@ -928,6 +928,14 @@ otbUnaryFunctorWithIndexImageFilter
     otbParserTest
     )
 
+# ----------------  otbVariableLengthVectorConverter  --------------------- #
+ADD_TEST(coTuVariableLengthVectorConverter ${COMMON_TESTS12}
+    otbVariableLengthVectorConverterNew
+    )
+
+#ADD_TEST(coTvVariableLengthVectorConverter ${COMMON_TESTS12}
+#    otbVariableLengthVectorConverter
+#    )
 
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ otbCommonTests13 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1087,6 +1095,7 @@ otbUnaryFunctorWithIndexImageFilter.cxx
 SET(BasicCommon_SRCS12
 otbCommonTests12.cxx
 otbParserTest.cxx
+otbVariableLengthVectorConverter.cxx
 )
 
 
diff --git a/Testing/Code/Common/otbCommonTests12.cxx b/Testing/Code/Common/otbCommonTests12.cxx
index f11a9e0d15..28e89d5763 100644
--- a/Testing/Code/Common/otbCommonTests12.cxx
+++ b/Testing/Code/Common/otbCommonTests12.cxx
@@ -28,4 +28,6 @@ void RegisterTests()
 {
   REGISTER_TEST(otbParserTestNew);
   REGISTER_TEST(otbParserTest);
+  REGISTER_TEST(otbVariableLengthVectorConverterNew);
+  //REGISTER_TEST(otbVariableLengthVectorConverter);
 }
diff --git a/Testing/Code/Common/otbVariableLengthVectorConverter.cxx b/Testing/Code/Common/otbVariableLengthVectorConverter.cxx
new file mode 100644
index 0000000000..d3e9a32ce1
--- /dev/null
+++ b/Testing/Code/Common/otbVariableLengthVectorConverter.cxx
@@ -0,0 +1,54 @@
+/*=========================================================================
+
+  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 "itkExceptionObject.h"
+#include <cstdlib>
+#include <cmath>
+
+#include "otbVariableLengthVectorConverter.h"
+
+int otbVariableLengthVectorConverterNew(int argc, char * argv[])
+{
+  typedef itk::VariableLengthVector<double>                      InputType0;
+  typedef std::vector< std::vector< double > >                   InputType1;
+  typedef std::vector< std::vector< std::complex< double > > >   InputType2;
+  typedef itk::FixedArray<double>                                InputType3;
+  
+  typedef float                                                  PrecisionType;
+  
+  typedef otb::VariableLengthVectorConverter<InputType0, PrecisionType>
+                                                                 ConverterType0;
+  typedef otb::VariableLengthVectorConverter<InputType1, PrecisionType>
+                                                                 ConverterType1;
+  typedef otb::VariableLengthVectorConverter<InputType2, PrecisionType>
+                                                                 ConverterType2;
+  typedef otb::VariableLengthVectorConverter<InputType3, PrecisionType>
+                                                                 ConverterType3;
+  
+  // Instantiating object
+  ConverterType0::Pointer converter0 = ConverterType0::New();
+  ConverterType1::Pointer converter1 = ConverterType1::New();
+  ConverterType2::Pointer converter2 = ConverterType2::New();
+  ConverterType3::Pointer converter3 = ConverterType3::New();
+  
+  std::cout << converter0 << std::endl;
+  std::cout << converter1 << std::endl;
+  std::cout << converter2 << std::endl;
+  std::cout << converter3 << std::endl;
+
+  return EXIT_SUCCESS;
+}
-- 
GitLab