From 9b8b1b8486aff45bc69ce1b7fa289b766be2ecf9 Mon Sep 17 00:00:00 2001
From: Arnaud Jaen <arnaud.jaen@c-s.fr>
Date: Thu, 15 Mar 2012 18:19:54 +0100
Subject: [PATCH] ENH: Modify ConcatenateVectorDataFilter to avoid scanning the
 largest vectorData (shallow copy)

---
 .../otbConcatenateVectorDataFilter.h          |  3 +-
 .../otbConcatenateVectorDataFilter.txx        | 89 ++++++++++++++-----
 .../otbPersistentImageToVectorDataFilter.h    | 12 +++
 .../otbPersistentImageToVectorDataFilter.txx  |  5 +-
 4 files changed, 86 insertions(+), 23 deletions(-)

diff --git a/Code/BasicFilters/otbConcatenateVectorDataFilter.h b/Code/BasicFilters/otbConcatenateVectorDataFilter.h
index 23a836e1f4..1db5d5d03b 100644
--- a/Code/BasicFilters/otbConcatenateVectorDataFilter.h
+++ b/Code/BasicFilters/otbConcatenateVectorDataFilter.h
@@ -34,6 +34,7 @@ namespace otb
  * Note that the input vectordatas must have the same node type,
  * this is due that vectordata creation does not support multiple geomtries
  * in a single vectordata.
+ * Warning : this filter does not create a deep copy of each node.
  *
  */
 template <class TVectorData>
@@ -82,7 +83,7 @@ protected:
   void GenerateData(void);
   
   /** Recursive method to visit efficiently the vectordata*/
-  void ProcessNode(TreeNodeType * source);
+  void ProcessNode(TreeNodeType * source, DataNodeType * outputDocument);
   
 private:
   ConcatenateVectorDataFilter(const Self &); //purposely not implemented
diff --git a/Code/BasicFilters/otbConcatenateVectorDataFilter.txx b/Code/BasicFilters/otbConcatenateVectorDataFilter.txx
index 7511fbf10a..8464c2aaec 100644
--- a/Code/BasicFilters/otbConcatenateVectorDataFilter.txx
+++ b/Code/BasicFilters/otbConcatenateVectorDataFilter.txx
@@ -21,6 +21,7 @@
 #include "otbConcatenateVectorDataFilter.h"
 
 #include "otbMath.h"
+#include "itkTimeProbe.h"
 
 namespace otb
 {
@@ -73,6 +74,9 @@ void
 ConcatenateVectorDataFilter<TVectorData>
 ::GenerateData()
 {
+  itk::TimeProbe tileChrono;
+  tileChrono.Start();
+
   // TODO : no checking is done on the inputs, do checking to avoid
   // TODO : Check if they are in the same coordinate system (tricky)
   
@@ -82,32 +86,75 @@ ConcatenateVectorDataFilter<TVectorData>
   //this->GetOutput()->SetMetaDataDictionary(this->GetInput(0)->GetMetaDataDictionary());
   
   // Prepare the output
-  typename DataNodeType::Pointer outputRoot = this->GetOutput()->GetDataTree()->GetRoot()->Get();
+  //typename DataNodeType::Pointer outputRoot = this->GetOutput()->GetDataTree()->GetRoot()->Get();
+  
+  // Retrieve the larger input
+  //itk::TimeProbe maxChrono;
+  //maxChrono.Start();
+  /*unsigned int maxIdx = 0;
+  int max = 0;
+  for(unsigned int idx = 0; idx < this->GetNumberOfInputs(); ++idx)
+    {
+      //std::cout<<"nb feature input "<<this->GetInput(idx)->Size()<<std::endl;
+      if (this->GetInput(idx)->Size() > max)
+      {
+         max = this->GetInput(idx)->Size();
+         maxIdx = idx;
+      }
+    }
+    maxChrono.Stop();
+    std::cout<< "Max took " << maxChrono.GetTotal() << " sec"<<std::endl;
+  */
+    
+  //std::cout<<"max index "<<maxIdx<<std::endl;
+  typename DataTreeType::Pointer outputTree = this->GetOutput()->GetDataTree();
+  typename TreeNodeType::Pointer inputRoot = const_cast<TreeNodeType *>(this->GetInput(0)->GetDataTree()->GetRoot());
+  
+  
+  outputTree->SetRoot(inputRoot);
+  
+  
+  typename DataNodeType::Pointer outputDocument = this->GetOutput()->GetDataTree()->GetRoot()->GetChild(0)->Get();
+  
+  //std::cout<<"node type (document ??) "<< outputDocument->GetNodeType() <<std::endl;
   
   // Adding the layer to the data tree
-  this->GetOutput()->GetDataTree()->Add(m_Document, outputRoot);
-  this->GetOutput()->GetDataTree()->Add(m_Folder, m_Document);
+//   this->GetOutput()->GetDataTree()->Add(m_Document, outputRoot);
+//   this->GetOutput()->GetDataTree()->Add(m_Folder, m_Document);
   
   // Retrieve all the inputs
-  for(unsigned int idx = 0; idx < this->GetNumberOfInputs(); ++idx)
+  for(unsigned int idx = 1; idx < this->GetNumberOfInputs(); ++idx)
     {
-    // Add the current vectordata
-    TreeNodeType *
-      inputRoot = const_cast<TreeNodeType *>(this->GetInput(idx)->GetDataTree()->GetRoot());
-    //
-    ProcessNode(inputRoot);
+      //std::cout<<"index "<<idx<<std::endl;
+      // Add the current vectordata
+      TreeNodeType *
+         inputRoot = const_cast<TreeNodeType *>(this->GetInput(idx)->GetDataTree()->GetRoot());
+      //
+      
+      itk::TimeProbe processNodeChrono;
+      processNodeChrono.Start();
+      
+      ProcessNode(inputRoot, outputDocument);
+      
+      processNodeChrono.Stop();
+      std::cout<< "Process Node (concatenate) took " << processNodeChrono.GetTotal() << " sec"<<std::endl;
+      
     }
-
+   //std::cout<<"nb feature output "<<this->GetOutput()->Size()<<std::endl;
+   
+   tileChrono.Stop();
+   std::cout<< "Concatenate vector data took " << tileChrono.GetTotal() << " sec"<<std::endl;
 }
 
 
 template <class TVectorData>
 void
 ConcatenateVectorDataFilter<TVectorData>
-::ProcessNode(TreeNodeType * source)
+::ProcessNode(TreeNodeType * source, DataNodeType * outputDocument)
 {
   if (source == 0)
     return;
+  
 
   // Get the children list from the input node
   ChildrenListType children = source->GetChildrenList();
@@ -123,52 +170,52 @@ ConcatenateVectorDataFilter<TVectorData>
       {
       case ROOT:
         {
-        ProcessNode((*it));
+        ProcessNode((*it), outputDocument);
         break;
         }
       case DOCUMENT:
         {
-        ProcessNode((*it));
+        ProcessNode((*it), outputDocument);
         break;
         }
       case FOLDER:
         {
-        ProcessNode((*it));
+        ProcessNode((*it), outputDocument);
         break;
         }
       case FEATURE_POINT:
         {
-        this->GetOutput()->GetDataTree()->Add(dataNode, m_Document);
+        this->GetOutput()->GetDataTree()->Add(dataNode, outputDocument);
         break;
         }
       case FEATURE_LINE:
         {
-        this->GetOutput()->GetDataTree()->Add(dataNode, m_Document);
+        this->GetOutput()->GetDataTree()->Add(dataNode, outputDocument);
         break;
         }
       case FEATURE_POLYGON:
         {
-        this->GetOutput()->GetDataTree()->Add(dataNode, m_Document);
+        this->GetOutput()->GetDataTree()->Add(dataNode, outputDocument);
         break;
         }
     case FEATURE_MULTIPOINT:
         {
-        ProcessNode((*it));
+        ProcessNode((*it), outputDocument);
         break;
         }
       case FEATURE_MULTILINE:
         {
-        ProcessNode((*it));
+        ProcessNode((*it), outputDocument);
         break;
         }
       case FEATURE_MULTIPOLYGON:
         {
-        ProcessNode((*it));
+        ProcessNode((*it), outputDocument);
         break;
         }
       case FEATURE_COLLECTION:
         {
-        ProcessNode((*it));
+        ProcessNode((*it), outputDocument);
         break;
         }
       }
diff --git a/Code/Common/otbPersistentImageToVectorDataFilter.h b/Code/Common/otbPersistentImageToVectorDataFilter.h
index af44060499..2e70071978 100644
--- a/Code/Common/otbPersistentImageToVectorDataFilter.h
+++ b/Code/Common/otbPersistentImageToVectorDataFilter.h
@@ -25,6 +25,8 @@
 #include "itkExtractImageFilter.h"
 
 #include "otbConcatenateVectorDataFilter.h"
+#include "otbOGRVectorDataIO.h"
+#include "itkMacro.h"
 
 namespace otb
 {
@@ -72,6 +74,9 @@ public:
 
   typedef otb::ConcatenateVectorDataFilter<OutputVectorDataType> ConcatenateVectorDataFilterType;
   typedef typename ConcatenateVectorDataFilterType::Pointer      ConcatenateVectorDataFilterPointerType;
+  
+  typedef otb::OGRVectorDataIO       OGRVectorDataIOType;
+  typedef typename OGRVectorDataIOType::Pointer   OGRVectorDataIOPointerType;
 
   /** Smart Pointer type to a DataObject. */
   typedef itk::DataObject::Pointer DataObjectPointer;
@@ -83,6 +88,10 @@ public:
   virtual void Reset(void);
 
   virtual void Synthetize(void);
+  
+  /** Specify the name of the output shapefile to write. */
+  itkSetStringMacro(FileName);
+  itkGetStringMacro(FileName);
 
 protected:
   PersistentImageToVectorDataFilter();
@@ -101,6 +110,9 @@ private:
   void operator =(const Self&); //purposely not implemented
 
   virtual OutputVectorDataPointerType ProcessTile() = 0;
+  
+  OGRVectorDataIOPointerType m_VectorDataIO;
+  std::string m_FileName;
 
 }; // end of class
 } // end namespace otb
diff --git a/Code/Common/otbPersistentImageToVectorDataFilter.txx b/Code/Common/otbPersistentImageToVectorDataFilter.txx
index 4c5b257c1e..1bfcd993fa 100644
--- a/Code/Common/otbPersistentImageToVectorDataFilter.txx
+++ b/Code/Common/otbPersistentImageToVectorDataFilter.txx
@@ -32,6 +32,8 @@ PersistentImageToVectorDataFilter<TImage, TOutputVectorData>
 {
   m_ExtractFilter = ExtractImageFilterType::New();
   m_OutputVectorData = OutputVectorDataType::New();
+  
+  m_VectorDataIO = OGRVectorDataIOType::New();
 }
 
 template<class TImage, class TOutputVectorData>
@@ -92,9 +94,10 @@ PersistentImageToVectorDataFilter<TImage, TOutputVectorData>
   // merge the result into the output vector data object
   OutputVectorDataPointerType output = GetOutputVectorData();
 
+
   ConcatenateVectorDataFilterPointerType concatenate = ConcatenateVectorDataFilterType::New();
-  concatenate->AddInput(currentTileVD);
   concatenate->AddInput(output);
+  concatenate->AddInput(currentTileVD);
   concatenate->Update();
 
   concatenate->GetOutput()->SetMetaDataDictionary(currentTileVD->GetMetaDataDictionary());
-- 
GitLab