From 22724050b4f95b42da13ffe1c3b8461bed73e6e2 Mon Sep 17 00:00:00 2001
From: Julien Malik <julien.malik@c-s.fr>
Date: Fri, 27 May 2011 08:52:37 +0200
Subject: [PATCH] ENH: add ParserConditionDataNodeFeatureFunction

---
 ...tbParserConditionDataNodeFeatureFunction.h | 116 +++++++++++++++
 ...ParserConditionDataNodeFeatureFunction.txx | 129 +++++++++++++++++
 Testing/Code/BasicFilters/CMakeLists.txt      |  28 ++++
 .../BasicFilters/otbBasicFiltersTests15.cxx   |   2 +
 ...ParserConditionDataNodeFeatureFunction.cxx | 133 ++++++++++++++++++
 5 files changed, 408 insertions(+)
 create mode 100644 Code/BasicFilters/otbParserConditionDataNodeFeatureFunction.h
 create mode 100644 Code/BasicFilters/otbParserConditionDataNodeFeatureFunction.txx
 create mode 100644 Testing/Code/BasicFilters/otbParserConditionDataNodeFeatureFunction.cxx

diff --git a/Code/BasicFilters/otbParserConditionDataNodeFeatureFunction.h b/Code/BasicFilters/otbParserConditionDataNodeFeatureFunction.h
new file mode 100644
index 0000000000..82a4c63d93
--- /dev/null
+++ b/Code/BasicFilters/otbParserConditionDataNodeFeatureFunction.h
@@ -0,0 +1,116 @@
+/*=========================================================================
+
+  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 __otbParserConditionDataNodeFeatureFunction_h
+#define __otbParserConditionDataNodeFeatureFunction_h
+
+#include "otbDataNodeImageFunction.h"
+#include "otbDataNode.h"
+#include "otbPolyLineImageConstIterator.h"
+#include "otbMaskMuParserFunctor.h"
+
+namespace otb
+{
+/** \class ParserConditionDataNodeFeatureFunction
+  * \brief Compute a ParserCondition based feature alongside a
+  * datanode.
+  *
+  * This function evaluate a condition alongside a datanode.
+  * The descriptor is the percentage of pixels iterated for which
+  * the condition is true.
+  *
+  * \ingroup Functions
+  * \sa DataNodeImageFunction
+  * \sa SpectralAngleDataNodeFeatureFunction
+  */
+
+template <
+class TImage,
+class TCoordRep = double,
+class TPrecision = double
+>
+class ITK_EXPORT ParserConditionDataNodeFeatureFunction :
+    public DataNodeImageFunction<TImage, std::vector<TPrecision>, TCoordRep, TPrecision>
+{
+public:
+  /** Standard class typedefs. */
+  typedef ParserConditionDataNodeFeatureFunction                         Self;
+  typedef DataNodeImageFunction<TImage, std::vector<TPrecision>, TCoordRep, TPrecision>
+                                                              Superclass;
+  typedef itk::SmartPointer<Self>                             Pointer;
+  typedef itk::SmartPointer<const Self>                       ConstPointer;
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self);
+
+  /** Run-time type information (and related methods). */
+  itkTypeMacro(ParserConditionDataNodeFeatureFunction, DataNodeImageFunction);
+
+  /** Some typedefs. */
+  typedef typename Superclass::DataNodeType           DataNodeType;
+  typedef typename DataNodeType::LineType             LineType;
+
+  typedef TImage                                      InputImageType;
+  typedef typename InputImageType::ConstPointer       InputImageConstPointer;
+  typedef typename InputImageType::PixelType          PixelType;
+  typedef typename InputImageType::InternalPixelType  ScalarRealType;
+  typedef typename InputImageType::IndexType          IndexType;
+  typedef typename InputImageType::IndexValueType     IndexValueType;
+
+  typedef TCoordRep                                   CoordRepType;
+
+  typedef TPrecision                                  PrecisionType;
+
+  typedef PolyLineImageConstIterator<InputImageType, LineType>
+                                                      ImageLineIteratorType;
+
+  typedef Functor::MaskMuParserFunctor<PixelType>      ParserConditionFunctorType;
+  typedef typename ParserConditionFunctorType::Pointer ParserConditionFunctorPointer;
+
+  typedef std::vector<PrecisionType>                  OutputType;
+
+  virtual OutputType Evaluate( const DataNodeType& node ) const;
+
+  std::string GetExpression(std::string expression) const
+  {
+    return m_ParserConditionFunctor->GetExpression();
+  }
+
+  void SetExpression(std::string expression)
+  {
+    m_ParserConditionFunctor->SetExpression(expression);
+  }
+
+protected:
+  ParserConditionDataNodeFeatureFunction();
+  virtual ~ParserConditionDataNodeFeatureFunction() {}
+  void PrintSelf(std::ostream& os, itk::Indent indent) const;
+
+private:
+  ParserConditionDataNodeFeatureFunction(const Self&); //purposely not implemented
+  void operator=(const Self&); //purposely not implemented
+
+  /** ParserCondition Functor */
+  ParserConditionFunctorPointer  m_ParserConditionFunctor;
+};
+
+}
+#ifndef OTB_MANUAL_INSTANTIATION
+#include "otbParserConditionDataNodeFeatureFunction.txx"
+#endif
+
+#endif
diff --git a/Code/BasicFilters/otbParserConditionDataNodeFeatureFunction.txx b/Code/BasicFilters/otbParserConditionDataNodeFeatureFunction.txx
new file mode 100644
index 0000000000..b151867fb1
--- /dev/null
+++ b/Code/BasicFilters/otbParserConditionDataNodeFeatureFunction.txx
@@ -0,0 +1,129 @@
+/*=========================================================================
+
+  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 __otbParserConditionDataNodeFeatureFunction_txx
+#define __otbParserConditionDataNodeFeatureFunction_txx
+
+#include "otbParserConditionDataNodeFeatureFunction.h"
+
+namespace otb
+{
+
+/**
+ * Constructor
+ */
+template <class TImage, class TCoordRep, class TPrecision>
+ParserConditionDataNodeFeatureFunction<TImage, TCoordRep, TPrecision>
+::ParserConditionDataNodeFeatureFunction()
+{
+  m_ParserConditionFunctor = ParserConditionFunctorType::New();
+}
+
+/**
+ * Standard "PrintSelf" method
+ */
+template <class TImage, class TCoordRep, class TPrecision>
+void
+ParserConditionDataNodeFeatureFunction<TImage, TCoordRep, TPrecision>
+::PrintSelf( std::ostream& os, itk::Indent indent) const
+{
+  Superclass::PrintSelf( os, indent );
+  //os << indent << "ParserCondition : "    << m_ParserConditionFunctor << std::endl;
+}
+
+template <class TImage, class TCoordRep, class TPrecision>
+typename ParserConditionDataNodeFeatureFunction<TImage, TCoordRep, TPrecision>
+::OutputType
+ ParserConditionDataNodeFeatureFunction<TImage, TCoordRep, TPrecision>
+::Evaluate( const DataNodeType& node ) const
+{
+  // The parser evaluation can't be const since the parser state
+  // changes at the first evaluation, but in fact we don't modify
+  // anything here.
+  // To fit with the rest of the framework, we try to keep the Evaluate
+  // function const
+  Self* _this = const_cast<Self*>(this);
+  ParserConditionFunctorType& parser = *(_this->m_ParserConditionFunctor);
+  // Ugly things over
+
+
+  const typename ImageLineIteratorType::PathType* path;
+
+  switch (node.GetNodeType())
+    {
+    case FEATURE_POINT:
+      {
+      itkExceptionMacro(<< "This DataNode type is not handle yet");
+      break;
+      }
+    case FEATURE_LINE:
+      {
+      path = node.GetLine();
+      break;
+      }
+    case FEATURE_POLYGON:
+      {
+      path = node.GetPolygonExteriorRing();
+      break;
+      }
+    default:
+      {
+      itkExceptionMacro(<< "This DataNode type is not handle yet");
+      break;
+      }
+    }
+
+  ImageLineIteratorType lineIt(this->GetInputImage(), path);
+  lineIt.GoToBegin();
+
+  double nbValidPixel = 0.;
+  double nbVisitedPixel = 0.;
+
+  while(!lineIt.IsAtEnd())
+    {
+    if(this->IsInsideBuffer(lineIt.GetIndex()))
+      {
+      if( parser(this->GetInputImage()->GetPixel(lineIt.GetIndex())) )
+        {
+        nbValidPixel += 1;
+        }
+      nbVisitedPixel += 1;
+      }
+    ++lineIt;
+    }
+
+  OutputType output;
+std::cout << "nbValidPixel " << nbValidPixel << std::endl;
+std::cout << "nbVisitedPixel " << nbVisitedPixel << std::endl;
+  if(nbVisitedPixel == 0)
+    {
+    output.push_back(static_cast<PrecisionType>(0.));
+    }
+  else
+    {
+    output.push_back(static_cast<PrecisionType>(nbValidPixel/nbVisitedPixel));
+    }
+
+  output.push_back(static_cast<PrecisionType>(nbValidPixel));
+  output.push_back(static_cast<PrecisionType>(nbVisitedPixel));
+std::cout << "output " << output[0] << std::endl;
+  return output;
+}
+
+} // end namespace otb
+
+#endif
diff --git a/Testing/Code/BasicFilters/CMakeLists.txt b/Testing/Code/BasicFilters/CMakeLists.txt
index 652ff40c0f..b2659a60b0 100644
--- a/Testing/Code/BasicFilters/CMakeLists.txt
+++ b/Testing/Code/BasicFilters/CMakeLists.txt
@@ -2059,6 +2059,33 @@ ADD_TEST(bfTvNDVIDataNodeFeatureFunction_Polygon ${BASICFILTERS_TESTS15}
 	0
 )
 
+
+ADD_TEST(bfTvParserConditionDataNodeFeatureFunction_Line_NDVI ${BASICFILTERS_TESTS15}
+ --compare-ogr ${NOTOL}
+  ${BASELINE_FILES}/bfTvNDVIDataNodeFeatureFunctionOutput_Line.shp
+  ${TEMP}/bfTvParserConditionDataNodeFeatureFunction_Line_NDVI.shp
+  otbParserConditionDataNodeFeatureFunction
+    ${INPUTDATA}/Dempster-Shafer/ROI_QB_TOULOUSE_ROADS.shp
+    ${INPUTDATA}/Dempster-Shafer/ROI_QB_TOULOUSE.TIF
+    ${INPUTDATA}/DEM/srtm_directory
+    ${TEMP}/bfTvParserConditionDataNodeFeatureFunction_Line_NDVI.shp
+    "ndvi(b3,b4) > 0.047"
+    0
+)
+
+ADD_TEST(bfTvParserConditionDataNodeFeatureFunction_Polygon_NDVI ${BASICFILTERS_TESTS15}
+ --compare-ogr ${NOTOL}
+  ${BASELINE_FILES}/bfTvNDVIDataNodeFeatureFunctionOutput_Polygon.shp
+  ${TEMP}/bfTvParserConditionDataNodeFeatureFunction_Polygon_NDVI.shp
+  otbParserConditionDataNodeFeatureFunction
+    ${INPUTDATA}/Dempster-Shafer/ROI_QB_TOULOUSE_BUILDINGS.shp
+    ${INPUTDATA}/Dempster-Shafer/ROI_QB_TOULOUSE.TIF
+    ${INPUTDATA}/DEM/srtm_directory
+    ${TEMP}/bfTvParserConditionDataNodeFeatureFunction_Polygon_NDVI.shp
+    "ndvi(b3,b4) > 0.047"
+    0
+)
+
 # ------------------  otbSpectralAngleDataNodeFeatureFunction   ------------------
 ADD_TEST(bfTuSpectralAngleDataNodeFeatureFunctionNew ${BASICFILTERS_TESTS15}
   otbSpectralAngleDataNodeFeatureFunctionNew
@@ -2395,6 +2422,7 @@ otbNDVIDataNodeFeatureFunction.cxx
 otbSpectralAngleDataNodeFeatureFunction.cxx
 otbDBOverlapDataNodeFeatureFunction.cxx
 otbRadiometryHomogenousWithNeighborhoodDataNodeFeatureFunction.cxx
+otbParserConditionDataNodeFeatureFunction.cxx
 )
 
 OTB_ADD_EXECUTABLE(otbBasicFiltersTests1 "${BasicFilters_SRCS1}" "OTBBasicFilters;OTBIO;OTBTesting")
diff --git a/Testing/Code/BasicFilters/otbBasicFiltersTests15.cxx b/Testing/Code/BasicFilters/otbBasicFiltersTests15.cxx
index 05859f0dca..66202f1b1e 100644
--- a/Testing/Code/BasicFilters/otbBasicFiltersTests15.cxx
+++ b/Testing/Code/BasicFilters/otbBasicFiltersTests15.cxx
@@ -27,6 +27,8 @@ void RegisterTests()
 {
   REGISTER_TEST(otbNDVIDataNodeFeatureFunctionNew);
   REGISTER_TEST(otbNDVIDataNodeFeatureFunction);
+  REGISTER_TEST(otbParserConditionDataNodeFeatureFunctionNew);
+  REGISTER_TEST(otbParserConditionDataNodeFeatureFunction);
   REGISTER_TEST(otbSpectralAngleDataNodeFeatureFunctionNew);
   REGISTER_TEST(otbSpectralAngleDataNodeFeatureFunction);
   REGISTER_TEST(otbRadiometryHomogenousWithNeighborhoodDataNodeFeatureFunctionNew);
diff --git a/Testing/Code/BasicFilters/otbParserConditionDataNodeFeatureFunction.cxx b/Testing/Code/BasicFilters/otbParserConditionDataNodeFeatureFunction.cxx
new file mode 100644
index 0000000000..e62307399f
--- /dev/null
+++ b/Testing/Code/BasicFilters/otbParserConditionDataNodeFeatureFunction.cxx
@@ -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.
+
+ =========================================================================*/
+
+#include "otbParserConditionDataNodeFeatureFunction.h"
+
+#include "otbVectorImage.h"
+#include "otbImageFileReader.h"
+#include "otbVectorData.h"
+#include "otbVectorDataFileReader.h"
+#include "otbVectorDataIntoImageProjectionFilter.h"
+#include "otbVectorDataFileWriter.h"
+#include "itkPreOrderTreeIterator.h"
+
+int otbParserConditionDataNodeFeatureFunctionNew(int argc, char* argv[])
+{
+  typedef double CoordRepType;
+  typedef double PrecisionType;
+  typedef otb::VectorImage<double, 2> ImageType;
+  typedef otb::ParserConditionDataNodeFeatureFunction<ImageType, CoordRepType, PrecisionType>
+      ParserConditionDataNodeFeaturefunctionType;
+
+  ParserConditionDataNodeFeaturefunctionType::Pointer
+      ParserConditionFeature = ParserConditionDataNodeFeaturefunctionType::New();
+
+  std::cout << ParserConditionFeature << std::endl;
+
+  return EXIT_SUCCESS;
+}
+
+int otbParserConditionDataNodeFeatureFunction(int argc, char* argv[])
+{
+  const char * inputVD = argv[1];
+  const char * inputImg = argv[2];
+  const char * DEMDir = argv[3];
+  const char * outputVD = argv[4];
+  const char * expression = argv[5];
+  int DisplayWarnings = atoi(argv[6]);
+
+  typedef double CoordRepType;
+  typedef double PrecisionType;
+  typedef otb::VectorImage<PrecisionType> ImageType;
+  typedef otb::ImageFileReader<ImageType> ImageReaderType;
+  typedef otb::VectorData<CoordRepType, 2, PrecisionType> VectorDataType;
+  typedef VectorDataType::DataNodeType DataNodeType;
+  typedef otb::VectorDataFileReader<VectorDataType> VectorDataReaderType;
+  typedef otb::VectorDataIntoImageProjectionFilter<VectorDataType, ImageType> VectorDataReProjFilter;
+  typedef otb::VectorDataFileWriter<VectorDataType> VectorDataWriterType;
+  typedef itk::PreOrderTreeIterator<VectorDataType::DataTreeType> TreeIteratorType;
+
+  typedef otb::ParserConditionDataNodeFeatureFunction<ImageType, CoordRepType, PrecisionType>
+      ParserConditionDataNodeFeaturefunctionType;
+  typedef ParserConditionDataNodeFeaturefunctionType::OutputType ParserConditionFeatureOutputType;
+
+  ImageReaderType::Pointer imgReader = ImageReaderType::New();
+  VectorDataReaderType::Pointer vdReader = VectorDataReaderType::New();
+  VectorDataReProjFilter::Pointer vdReProjFilter = VectorDataReProjFilter::New();
+  VectorDataWriterType::Pointer vdWriter = VectorDataWriterType::New();
+  ParserConditionDataNodeFeaturefunctionType::Pointer
+      ParserConditionFeatureFunction = ParserConditionDataNodeFeaturefunctionType::New();
+
+  if (!DisplayWarnings)
+    {
+    imgReader->SetGlobalWarningDisplay(0);
+    }
+
+  vdReader->SetFileName(inputVD);
+  vdReader->Update();
+
+  imgReader->SetFileName(inputImg);
+  imgReader->UpdateOutputInformation();
+  imgReader->Update(); //Needed to set m_EndIndex, m_StartIndex in otbDataNodeImageFunction
+
+  vdReProjFilter->SetInputImage(imgReader->GetOutput());
+  vdReProjFilter->SetInputVectorData(vdReader->GetOutput());
+  vdReProjFilter->SetDEMDirectory(DEMDir);
+  vdReProjFilter->SetUseOutputSpacingAndOriginFromImage(true);
+  vdReProjFilter->Update();
+
+  ParserConditionFeatureFunction->SetExpression("ndvi(b3,b4) > 0.047");
+  ParserConditionFeatureFunction->SetInputImage(imgReader->GetOutput());
+
+  // Output
+  VectorDataType::Pointer outVD = VectorDataType::New();
+  // Retrieving root node
+  DataNodeType::Pointer root = outVD->GetDataTree()->GetRoot()->Get();
+  // Create the document node
+  DataNodeType::Pointer document = DataNodeType::New();
+  document->SetNodeType(otb::DOCUMENT);
+  // Adding the layer to the data tree
+  outVD->GetDataTree()->Add(document, root);
+  // Create the folder node
+  DataNodeType::Pointer folder = DataNodeType::New();
+  folder->SetNodeType(otb::FOLDER);
+  // Adding the layer to the data tree
+  outVD->GetDataTree()->Add(folder, document);
+
+  TreeIteratorType itVector(vdReProjFilter->GetOutput()->GetDataTree());
+  itVector.GoToBegin();
+  while (!itVector.IsAtEnd())
+    {
+    if (itVector.Get()->IsLineFeature() || itVector.Get()->IsPolygonFeature())
+      {
+      const DataNodeType::Pointer currentGeometry = itVector.Get();
+      ParserConditionFeatureOutputType currentResult;
+      currentResult = ParserConditionFeatureFunction->Evaluate(*(currentGeometry.GetPointer()));
+      currentGeometry->SetFieldAsDouble("NDVI", (double) (currentResult[0]));
+      outVD->GetDataTree()->Add(currentGeometry, folder);
+      }
+    ++itVector;
+    }
+
+  vdWriter->SetInput(outVD);
+  vdWriter->SetFileName(outputVD);
+  vdWriter->Update();
+
+  return EXIT_SUCCESS;
+}
+
-- 
GitLab