From 933031bf858de26df6589bbd6c9073a6e090eab8 Mon Sep 17 00:00:00 2001
From: Otmane Lahlou <otmane.lahlou@c-s.fr>
Date: Thu, 3 Mar 2011 12:06:01 +0100
Subject: [PATCH] ENH : Add GraftOutput methods to VectorDataSource and
 override Graft method in VectorData (Output in mini-pipeline can be a
 VectorData now)

---
 Code/Common/otbVectorData.h         |  9 +++++++
 Code/Common/otbVectorData.txx       | 41 +++++++++++++++++++++++++++++
 Code/Common/otbVectorDataSource.h   | 18 +++++++++++++
 Code/Common/otbVectorDataSource.txx | 41 +++++++++++++++++++++++++++++
 4 files changed, 109 insertions(+)

diff --git a/Code/Common/otbVectorData.h b/Code/Common/otbVectorData.h
index e6d250cee5..0969fd4654 100644
--- a/Code/Common/otbVectorData.h
+++ b/Code/Common/otbVectorData.h
@@ -118,6 +118,15 @@ public:
     physicalPoint[0] = point[0] * m_Spacing[0] + m_Origin[0];
     physicalPoint[1] = point[1] * m_Spacing[1] + m_Origin[1];
   }
+  
+  /** Graft the data and information from one VectorData to another. This
+   * is a convenience method to setup a second VectorData with all the meta
+   * information of another VectorData and use the same DataTree
+   * Note that this method is different than just using two
+   * SmartPointers to the same VectorData since separate DataObjects are
+   * still maintained. This method is similar to
+   * VectorDataSource::GraftOutput(). */
+  virtual void Graft(const itk::DataObject *data);
 
 protected:
   /** Constructor */
diff --git a/Code/Common/otbVectorData.txx b/Code/Common/otbVectorData.txx
index ea804149ac..094f43ee71 100644
--- a/Code/Common/otbVectorData.txx
+++ b/Code/Common/otbVectorData.txx
@@ -154,6 +154,47 @@ VectorData<TPrecision, VDimension, TValuePrecision>
     ++it;
     }
 }
+
+template <class TPrecision, unsigned int VDimension, class TValuePrecision>
+void
+VectorData<TPrecision, VDimension, TValuePrecision>
+::Graft(const itk::DataObject *data)
+{
+  // call the superclass' implementation
+  Superclass::Graft( data );
+  
+  if ( data )
+    {
+    // Attempt to cast data to an Image
+    const Self * vdData;
+
+    try
+      {
+      vdData = dynamic_cast<const Self *>( data );
+      }
+    catch( ... )
+      {
+      return;
+      }
+    
+    if ( vdData )
+      {
+      // Copy all the needed data : DataTree, spacing, origin and
+      // Projection Ref
+      m_DataTree = const_cast<DataTreeType*> (vdData->GetDataTree());
+      this->SetSpacing(vdData->GetSpacing());
+      this->SetOrigin(vdData->GetOrigin());
+      this->SetProjectionRef(vdData->GetProjectionRef());
+      }
+    else
+      {
+      // pointer could not be cast back down
+      itkExceptionMacro( << "otb::VectorData::Graft() cannot cast "
+                         << typeid(data).name() << " to "
+                         << typeid(const Self *).name() );
+      }
+    }
+}
 } // end namespace otb
 
 #endif
diff --git a/Code/Common/otbVectorDataSource.h b/Code/Common/otbVectorDataSource.h
index b028e9d78c..14b6d35933 100644
--- a/Code/Common/otbVectorDataSource.h
+++ b/Code/Common/otbVectorDataSource.h
@@ -57,6 +57,24 @@ public:
   typedef TOutputVectorData                   OutputVectorDataType;
   typedef typename TOutputVectorData::Pointer OutputVectorDataPointer;
 
+  /** Graft the specified DataObject onto this ProcessObject's output.
+   * This method grabs a handle to the specified DataObject's bulk
+   * data to used as its output's own bulk data. 
+   * Most importantly, however, it leaves the Source ivar untouched so
+   * the original pipeline routing is intact. This method is used when 
+   * a process object is implemented using a mini-pipeline which is
+   * defined in its GenerateData() method.  
+   *  */
+  virtual void GraftOutput(itk::DataObject *output);
+
+  /** Graft the specified data object onto this ProcessObject's idx'th
+   * output. This is similar to the GraftOutput method except it
+   * allows you to specify which output is affected. The specified index
+   * must be a valid output number (less than
+   * ProcessObject::GetNumberOfOutputs()). See the GraftOutput for
+   * general usage information. */
+  virtual void GraftNthOutput(unsigned int idx, itk::DataObject *output);
+
   /** Overriding GetOutput() method */
   virtual OutputVectorDataType* GetOutput(void);
   virtual OutputVectorDataType* GetOutput(unsigned int idx);
diff --git a/Code/Common/otbVectorDataSource.txx b/Code/Common/otbVectorDataSource.txx
index bc5560d0ed..a4e92caaa3 100644
--- a/Code/Common/otbVectorDataSource.txx
+++ b/Code/Common/otbVectorDataSource.txx
@@ -40,6 +40,47 @@ VectorDataSource<TOutputVectorData>
 {
 }
 
+/**
+ * 
+ */
+
+template <class TOutputVectorData>
+void
+VectorDataSource<TOutputVectorData>
+::GraftOutput(itk::DataObject *graft)
+{
+  this->GraftNthOutput(0, graft);
+}
+
+/**
+ * 
+ */
+
+template <class TOutputVectorData>
+void
+VectorDataSource<TOutputVectorData>
+::GraftNthOutput(unsigned int idx, itk::DataObject *graft)
+{
+  if ( idx >= this->GetNumberOfOutputs() )
+    {
+    itkExceptionMacro(<<"Requested to graft output " << idx << 
+        " but this filter only has " << this->GetNumberOfOutputs() << " Outputs.");
+    }  
+
+  if ( !graft )
+    {
+    itkExceptionMacro(<<"Requested to graft output that is a NULL pointer" );
+    }
+
+  // we use the process object method since all out output may not be
+  // of the same type
+  itk::DataObject * output = this->ProcessObject::GetOutput(idx);
+
+  // Call GraftImage to copy meta-information, regions, and the pixel container
+  output->Graft( graft );
+}
+
+
 template <class TOutputVectorData>
 void
 VectorDataSource<TOutputVectorData>
-- 
GitLab