diff --git a/Code/Projections/CMakeLists.txt b/Code/Projections/CMakeLists.txt
index 58723d4ecb824139d4a80b080f58a2e3400caf05..772742780d65cff7c2a5faaf2fc1a5e6bf33a3ef 100644
--- a/Code/Projections/CMakeLists.txt
+++ b/Code/Projections/CMakeLists.txt
@@ -6,7 +6,7 @@ IF( NOT OTB_USE_CURL )
 ENDIF( NOT OTB_USE_CURL )
 
 ADD_LIBRARY(OTBProjections ${OTBProjections_SRCS})
-TARGET_LINK_LIBRARIES(OTBProjections OTBIO)
+TARGET_LINK_LIBRARIES(OTBProjections OTBIO OTBOGRAdapters)
 
 IF(OTB_LIBRARY_PROPERTIES)
   SET_TARGET_PROPERTIES(OTBProjections PROPERTIES ${OTB_LIBRARY_PROPERTIES})
diff --git a/Code/Projections/otbGeometriesProjectionFilter.cxx b/Code/Projections/otbGeometriesProjectionFilter.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..e1d579df013aaec7be3e51c92d082700e0937ec9
--- /dev/null
+++ b/Code/Projections/otbGeometriesProjectionFilter.cxx
@@ -0,0 +1,280 @@
+/*=========================================================================
+
+  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.
+
+=========================================================================*/
+
+/*===========================================================================*/
+/*===============================[ Includes ]================================*/
+/*===========================================================================*/
+#include "otbGeometriesProjectionFilter.h"
+#include <boost/type_traits/is_same.hpp>
+#include <boost/mpl/assert.hpp>
+#include "ogr_srs_api.h" // OCTDestroyCoordinateTransformation
+#include "ogr_spatialref.h" // OGRCoordinateTransformation
+#include "itkMacro.h"
+#include "otbGeometriesSet.h"
+#include "itkMetaDataObject.h"
+#include "otbOGRGeometryWrapper.h"
+#include "otbOGRGeometriesVisitor.h"
+
+
+/*===========================================================================*/
+/*===============================[ constants ]===============================*/
+/*===========================================================================*/
+namespace
+{ // Anonymous namespace
+const double k_averageElevation = -32768.0;
+} // Anonymous namespace
+
+/*===========================================================================*/
+/*======================[ Reprojection Transformation ]======================*/
+/*===========================================================================*/
+
+
+template <typename TGeometry>
+otb::ogr::UniqueGeometryPtr
+otb::ReprojectTransformationFunctor::ByCopy::operator()(TGeometry const* in) const
+{
+  boost::interprocess::unique_ptr<TGeometry, ogr::internal::GeometryDeleter>
+    out(in ? static_cast <TGeometry*>(in->clone()) : 0); // OGR clone doesn't use covariant return ...
+  if (out)
+    m_Reprojector.do_transform(*out);
+  ogr::UniqueGeometryPtr res(out.release());
+  return boost::move(res);
+}
+
+template <typename TGeometry>
+void
+otb::ReprojectTransformationFunctor::InPlace::operator()(TGeometry * inout) const
+{
+  if (inout)
+    m_Reprojector.do_transform(*inout);
+}
+
+#if 0
+void do_transform(OGRLinearRing & g) const
+{
+  assert(!"don't know how to reproject a ring yet");
+}
+#endif
+
+void otb::ReprojectTransformationFunctor::do_transform(OGRPoint & g) const
+{
+  typedef InternalTransformType::InputPointType  InputPointType;
+  typedef InternalTransformType::OutputPointType OutputPointType;
+  // in our case:
+  BOOST_MPL_ASSERT((boost::is_same<InputPointType, OutputPointType>));
+  const double rawPoint[] = { g.getX(), g.getY() };
+  const InputPointType inPoint(rawPoint);
+  const OutputPointType outPoint = m_Transform->TransformPoint(inPoint);
+  g.setX(outPoint[0]);
+  g.setY(outPoint[1]);
+}
+
+void otb::ReprojectTransformationFunctor::do_transform(OGRLineString & g) const
+{
+  OGRPoint point;
+  for (int i=0, N=g.getNumPoints(); i!=N; ++i)
+    {
+    g.getPoint(i, &point);
+    do_transform(point); // no need to go through the redispatch cycle
+    g.setPoint(i, &point);
+    }
+}
+
+#if 0
+void otb::ReprojectTransformationFunctor::do_transform(OGRCurve & g) const
+{
+  assert(!"OGRCurve is just an interface, they can't be reprojected yet");
+}
+#endif
+
+void otb::ReprojectTransformationFunctor::do_transform(OGRPolygon & g) const
+{
+  // Note: OGRPolygon interface states that rings obtained through
+  // getInteriorRing() and getExteriorRing() shall not be modified.
+  // In this context, it seems to make sense as it gives a direct access to the
+  // ring (yes this is a de-encapsulation), and the polygon is a fresh one has
+  // just been cloned in the () operator.
+  // The fact that OGRPolygon::transform() directly works on each sub-ring seems
+  // to confirm that hyppothesis.
+  for (int i=0, N=g.getNumInteriorRings(); i!=N; ++i)
+    {
+    OGRLinearRing * ring = g.getInteriorRing(i);
+    assert(ring && "Rings in polygons are not expected to be nil");
+    if (ring)
+      {
+      do_transform(*ring); // no need to go through the redispatch cycle
+      // how to commit the change ? Are ring modifications automatically commited ?
+      }
+    }
+  OGRLinearRing * ring = g.getExteriorRing();
+  assert(ring && "Rings in polygons are not expected to be nil");
+  if (ring)
+    {
+    do_transform(*ring); // no need to go through the redispatch cycle
+    // how to commit the change ? Are ring modifications automatically commited ?
+    }
+}
+
+#if 0
+void otb::ReprojectTransformationFunctor::do_transform(OGRSurface & g) const
+{
+  assert(!"OGRSurface is just an interface, they can't be reprojected yet");
+}
+
+void otb::ReprojectTransformationFunctor::do_transform(OGRMultiLineString & g) const
+{
+}
+
+void otb::ReprojectTransformationFunctor::do_transform(OGRMultiPoint & g) const
+{
+}
+
+void otb::ReprojectTransformationFunctor::do_transform(OGRMultiPolygon & g) const
+{
+}
+#endif
+
+void otb::ReprojectTransformationFunctor::do_transform(OGRGeometryCollection & col) const
+{
+  for (int i=0, N=col.getNumGeometries(); i!=N; ++i)
+    {
+    OGRGeometry * g = col.getGeometryRef(i);
+    assert(g && "geometries to transform shall not be null");
+    apply_inplace(g);
+    }
+}
+
+otb::ogr::UniqueGeometryPtr
+otb::ReprojectTransformationFunctor::operator()(OGRGeometry const* in) const
+// otb::ReprojectTransformationFunctor::apply(OGRGeometry const* in) const
+{
+  otb::ogr::UniqueGeometryPtr res
+    = ogr::apply<otb::ogr::UniqueGeometryPtr>(in, ByCopy(*this));
+  return boost::move(res);
+}
+
+void otb::ReprojectTransformationFunctor::apply_inplace(OGRGeometry * inout) const
+{
+  if (inout)
+    ogr::apply<void>(inout, InPlace(*this));
+}
+
+/*===========================================================================*/
+/*======================[ GeometriesProjectionFilter ]=======================*/
+/*===========================================================================*/
+
+otb::GeometriesProjectionFilter::GeometriesProjectionFilter()
+: InputImageReference(*this)
+, OutputImageReference(*this)
+{
+}
+
+/*virtual*/
+otb::GeometriesProjectionFilter::~GeometriesProjectionFilter()
+{
+}
+
+/*virtual*/
+void otb::GeometriesProjectionFilter::GenerateOutputInformation(void)
+{
+  Superclass::GenerateOutputInformation();
+
+  OutputGeometriesType::Pointer  output = this->GetOutput();
+  itk::MetaDataDictionary& dict = output->GetMetaDataDictionary();
+
+  itk::EncapsulateMetaData<std::string>(dict, MetaDataKey::ProjectionRefKey, m_OutputProjectionRef);
+}
+
+/*virtual*/
+void otb::GeometriesProjectionFilter::FinalizeInitialisation()
+{
+  m_Transform = InternalTransformType::New();
+
+  InputGeometriesType::ConstPointer   input      = this->GetInput();
+  const itk::MetaDataDictionary&      inputDict  = input->GetMetaDataDictionary();
+  OutputGeometriesType::Pointer       output     = this->GetOutput();
+  itk::MetaDataDictionary&            outputDict = output->GetMetaDataDictionary();
+
+  // m_Transform->SetInputDictionary(input->GetMetaDataDictionary());
+  m_Transform->SetInputDictionary(inputDict);
+  m_Transform->SetOutputDictionary(output->GetMetaDataDictionary());
+
+  m_Transform->SetInputProjectionRef(m_InputProjectionRef);
+  m_Transform->SetOutputProjectionRef(m_OutputProjectionRef);
+  m_Transform->SetInputKeywordList(m_InputKeywordList);
+  m_Transform->SetOutputKeywordList(m_OutputKeywordList);
+  m_Transform->SetDEMDirectory(m_DEMDirectory);
+  m_Transform->SetGeoidFile(m_GeoidFile);
+  m_Transform->SetAverageElevation(k_averageElevation);
+
+  m_Transform->SetInputSpacing(InputImageReference.GetSpacing());
+  m_Transform->SetInputOrigin(InputImageReference.GetOrigin());
+  m_Transform->SetOutputSpacing(OutputImageReference.GetSpacing());
+  m_Transform->SetOutputOrigin(OutputImageReference.GetOrigin());
+
+  m_Transform->InstanciateTransform();
+
+  m_TransformationFunctor->SetOnePointTransformation(m_Transform);
+
+  // retrieve the output projection ref
+  // if it is not specified and end up being geographic,
+  // only the m_Transform will know
+  m_OutputProjectionRef = m_Transform->GetOutputProjectionRef();
+
+  //If the projection information for the output is provided, propagate it
+
+  if (m_OutputKeywordList.GetSize() != 0)
+    {
+    itk::EncapsulateMetaData<ImageKeywordlist>(outputDict, MetaDataKey::OSSIMKeywordlistKey, m_OutputKeywordList);
+    }
+  if (!m_OutputProjectionRef.empty())
+    {
+    itk::EncapsulateMetaData<std::string>(outputDict, MetaDataKey::ProjectionRefKey, m_OutputProjectionRef);
+    }
+  output->SetImageReference(OutputImageReference);
+}
+
+/*virtual*/
+OGRSpatialReference* otb::GeometriesProjectionFilter::DoDefineNewLayerSpatialReference(
+  ogr::Layer const& source) const
+{
+  if (!m_OutputProjectionRef.empty())
+    {
+    char const* wkt_string = m_OutputProjectionRef.c_str();
+    OGRSpatialReference * res = static_cast <OGRSpatialReference*>(OSRNewSpatialReference(wkt_string));
+    return res;
+    }
+  else
+    {
+    return 0;
+    }
+}
+
+/*virtual*/
+void otb::GeometriesProjectionFilter::DoProcessLayer(ogr::Layer const& source, ogr::Layer & destination) const
+{
+  // std::cout << "GPF::DoProcessLayer: L("<<source.GetName()<<") -> L("<<destination.GetName()<<") ...\n";
+  if (source != destination)
+    {
+    m_TransformationFunctor(source, destination); // if TransformedElementType == layer
+    }
+  else
+    {
+    m_TransformationFunctor(destination); // if TransformedElementType == layer
+    }
+}
diff --git a/Code/Projections/otbGeometriesProjectionFilter.h b/Code/Projections/otbGeometriesProjectionFilter.h
new file mode 100644
index 0000000000000000000000000000000000000000..448b98b69ae7d7a134b91954ae6b49719a3adbc4
--- /dev/null
+++ b/Code/Projections/otbGeometriesProjectionFilter.h
@@ -0,0 +1,191 @@
+/*=========================================================================
+
+  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 __otbGeometriesProjectionFilter_h
+#define __otbGeometriesProjectionFilter_h
+
+#include "otbGeometriesToGeometriesFilter.h"
+#include "otbOGRGeometryWrapper.h"
+#include "otbImageReference.h"
+#include "itkTransform.h"
+#include "otbGenericRSTransform.h"
+
+class OGRCoordinateTransformation;
+
+namespace otb
+{
+
+struct ReprojectTransformationFunctor
+{
+  typedef OGRGeometry TransformedElementType;
+
+  struct ByCopy
+    {
+    ByCopy(ReprojectTransformationFunctor const& reprojector) : m_Reprojector(reprojector){}
+    template <typename TGeometry>
+      ogr::UniqueGeometryPtr operator()(TGeometry const* in) const;
+  private:
+    ReprojectTransformationFunctor const& m_Reprojector;
+    };
+
+  struct InPlace
+    {
+    InPlace(ReprojectTransformationFunctor const& reprojector) : m_Reprojector(reprojector){}
+    template <typename TGeometry>
+      void operator()(TGeometry * inout) const;
+  private:
+    ReprojectTransformationFunctor const& m_Reprojector;
+    };
+
+
+  ogr::UniqueGeometryPtr operator()(OGRGeometry const* in) const;
+  // ogr::UniqueGeometryPtr apply(OGRGeometry const* in) const;
+  void apply_inplace          (OGRGeometry * inout) const;
+
+  typedef otb::GenericRSTransform<double, 2, 2>   InternalTransformType;
+  typedef InternalTransformType::Pointer          InternalTransformPointerType;
+  void SetOnePointTransformation(InternalTransformPointerType transform)
+    {
+    m_Transform = transform;
+    }
+private:
+  void do_transform(OGRPoint              & g) const;
+  // void do_transform(OGRLinearRing         & g) const;
+  void do_transform(OGRLineString         & g) const;
+  // void do_transform(OGRCurve              & g) const;
+  void do_transform(OGRPolygon            & g) const;
+#if 0
+  void do_transform(OGRSurface            & g) const;
+  void do_transform(OGRMultiLineString    & g) const;
+  void do_transform(OGRMultiPoint         & g) const;
+  void do_transform(OGRMultiPolygon       & g) const;
+#endif
+  void do_transform(OGRGeometryCollection & g) const;
+
+  InternalTransformPointerType m_Transform;
+};
+
+
+class ITK_EXPORT GeometriesProjectionFilter : public GeometriesToGeometriesFilter
+{
+public:
+  /**\name Standard ITK typedefs */
+  //@{
+  typedef GeometriesProjectionFilter    Self;
+  typedef GeometriesToGeometriesFilter  Superclass;
+  typedef itk::SmartPointer<Self>       Pointer;
+  typedef itk::SmartPointer<const Self> ConstPointer;
+  //@}
+
+  /**\name Standard macros */
+  //@{
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self);
+
+  /** Run-time type information (and related methods). */
+  itkTypeMacro(GeometriesProjectionFilter, GeometriesToGeometriesFilter);
+  //@}
+
+  /**\name I/O typedefs */
+  //@{
+  typedef Superclass::InputGeometriesType        InputGeometriesType;
+  // typedef Superclass::InputGeometriesPointer  InputGeometriesPointer;
+  typedef Superclass::OutputGeometriesType       OutputGeometriesType;
+  // typedef Superclass::OutputGeometriesPointer OutputGeometriesPointer;
+  //@}
+
+  /**\name Class typedefs */
+  //@{
+  typedef ogr::ImageReference<double>                            ImageReference;
+  //@}
+
+private:
+  virtual OGRSpatialReference* DoDefineNewLayerSpatialReference(ogr::Layer const& source) const;
+  virtual void DoProcessLayer(ogr::Layer const& source, ogr::Layer & destination) const;
+  virtual void FinalizeInitialisation();
+
+protected:
+  /** Default constructor. */
+  GeometriesProjectionFilter();
+  /** Destructor. */
+  virtual ~GeometriesProjectionFilter();
+
+  virtual void GenerateOutputInformation(void);
+
+public:
+  ImageReference InputImageReference;
+  ImageReference OutputImageReference;
+
+  /**\name Keywords lists accessors and mutators */
+  //@{
+  itkGetMacro(InputKeywordList, ImageKeywordlist);
+  void SetInputKeywordList(const ImageKeywordlist& kwl)
+    {
+    this->m_InputKeywordList = kwl;
+    this->Modified();
+    }
+
+  itkGetMacro(OutputKeywordList, ImageKeywordlist);
+  void SetOutputKeywordList(const ImageKeywordlist& kwl)
+    {
+    this->m_OutputKeywordList = kwl;
+    this->Modified();
+    }
+  //@}
+
+  /**\name Projection references accessors and mutators */
+  //@{
+  itkSetStringMacro(InputProjectionRef);
+  itkGetStringMacro(InputProjectionRef);
+
+  itkSetStringMacro(OutputProjectionRef);
+  itkGetStringMacro(OutputProjectionRef);
+  //@}
+private:
+  /**\name Functor definition */
+  //@{
+  typedef ReprojectTransformationFunctor                          TransformationFunctorType;
+  typedef TransformationFunctorType::TransformedElementType       TransformedElementType;
+  typedef TransformationFunctorDispatcher<TransformationFunctorType, TransformedElementType>
+                                                                  TransformationFunctorDispatcherType;
+
+  TransformationFunctorDispatcherType             m_TransformationFunctor;
+  //@}
+
+  /**\name 1 Point Transformation definition */
+  //@{
+  typedef TransformationFunctorType::InternalTransformType        InternalTransformType;
+  typedef TransformationFunctorType::InternalTransformPointerType InternalTransformPointerType;
+
+  InternalTransformPointerType                    m_Transform;
+  //@}
+
+  std::string                                     m_InputProjectionRef; // in WKT format!
+  std::string                                     m_OutputProjectionRef; // in WKT format!
+  ImageKeywordlist                                m_InputKeywordList;
+  ImageKeywordlist                                m_OutputKeywordList;
+
+  std::string                                     m_DEMDirectory;
+  std::string                                     m_GeoidFile;
+};
+} // end namespace otb
+
+#ifndef OTB_MANUAL_INSTANTIATION
+// #include "otbGeometriesProjectionFilter.txx"
+#endif
+
+#endif // __otbGeometriesProjectionFilter_h
diff --git a/Code/UtilitiesAdapters/OGRAdapters/otbGeometriesSet.cxx b/Code/UtilitiesAdapters/OGRAdapters/otbGeometriesSet.cxx
index d2c268574357d89e971550077abac253ad2b44e6..c83078511eebf8c26dcd71dee8d0730c21df6867 100644
--- a/Code/UtilitiesAdapters/OGRAdapters/otbGeometriesSet.cxx
+++ b/Code/UtilitiesAdapters/OGRAdapters/otbGeometriesSet.cxx
@@ -58,17 +58,20 @@ otb::ogr::Layer & getRef(otb::ogr::Layer & layer)
 /*===========================================================================*/
 otb::GeometriesSet::GeometriesSet()
 : m_geometriesSet(otb::ogr::DataSource::New())
+, m_ImageReference(*this)
 {
 }
 
 otb::GeometriesSet::GeometriesSet(ogr::DataSource::Pointer datasource)
 : m_geometriesSet(datasource)
+, m_ImageReference(*this)
 {
   assert(datasource && "unexpected nil datasource");
 }
 
 otb::GeometriesSet::GeometriesSet(ogr::Layer layer)
 : m_geometriesSet(layer)
+, m_ImageReference(*this)
 {
 }
 
@@ -148,3 +151,28 @@ void otb::GeometriesSet::PrintSelf(std::ostream& os, itk::Indent indent) const
 {
   this->apply(Printer(os, indent));
 }
+
+/*===========================================================================*/
+/*=========================[ GetMetaDataDictionary ]=========================*/
+/*===========================================================================*/
+struct MetaDataDictionaryGetter : boost::static_visitor<itk::MetaDataDictionary&>
+{
+  itk::MetaDataDictionary& operator()(otb::ogr::Layer layer) const
+    {
+    return layer.GetMetaDataDictionary();
+    }
+  itk::MetaDataDictionary& operator()(otb::ogr::DataSource::Pointer datasource) const
+    {
+    return datasource->GetMetaDataDictionary();
+    }
+};
+
+itk::MetaDataDictionary & otb::GeometriesSet::GetMetaDataDictionary()
+{
+  return this->apply(MetaDataDictionaryGetter());
+}
+
+itk::MetaDataDictionary const& otb::GeometriesSet::GetMetaDataDictionary() const
+{
+  return const_cast <GeometriesSet *>(this)->GetMetaDataDictionary();
+}
diff --git a/Code/UtilitiesAdapters/OGRAdapters/otbGeometriesSet.h b/Code/UtilitiesAdapters/OGRAdapters/otbGeometriesSet.h
index 4efc6f40936078b6e8380d1bf922e74cc7538240..ff613e85c2e41e57758e5b32c03efdbd7c383760 100644
--- a/Code/UtilitiesAdapters/OGRAdapters/otbGeometriesSet.h
+++ b/Code/UtilitiesAdapters/OGRAdapters/otbGeometriesSet.h
@@ -22,6 +22,12 @@
 #include "itkDataObject.h"
 // #include "otbOGRLayerWrapper.h"
 #include "otbOGRDataSourceWrapper.h"
+#include "otbImageReference.h"
+
+namespace itk
+{
+class MetaDataDictionary;
+}
 
 namespace otb
 {
@@ -107,6 +113,23 @@ public:
    */
   bool IsSet() const;
 
+  /**\name Meta data dictionary */
+  //@{
+  itk::MetaDataDictionary      & GetMetaDataDictionary();
+  itk::MetaDataDictionary const& GetMetaDataDictionary() const;
+  //@}
+
+  /**\name Image reference (spacing + origin) */
+  //@{
+  typedef ogr::ImageReference<double>                            ImageReference;
+  /** imageReference setter. */
+  void SetImageReference(ImageReference const& imageReference)
+    { m_ImageReference = imageReference; }
+  /** imageReference getter. */
+  ImageReference const& GetImageReference() const
+    { return m_ImageReference; }
+  //@}
+
 protected:
   /** Default constructor.
    * This actual geometries set is an in-memory \c otb::ogr::DataSource.
@@ -130,6 +153,7 @@ protected:
 private:
   typedef boost::variant<ogr::DataSource::Pointer, ogr::Layer> AnyGeometriesSetType;
   AnyGeometriesSetType m_geometriesSet;
+  ImageReference       m_ImageReference;
   };
 
 } // end namespace otb
diff --git a/Code/UtilitiesAdapters/OGRAdapters/otbGeometriesToGeometriesFilter.cxx b/Code/UtilitiesAdapters/OGRAdapters/otbGeometriesToGeometriesFilter.cxx
index 743d3e1596fcc1ea1c14e0e34457af2cd85b5fcb..44b89a5307fff917773872c7831e118fa08640bb 100644
--- a/Code/UtilitiesAdapters/OGRAdapters/otbGeometriesToGeometriesFilter.cxx
+++ b/Code/UtilitiesAdapters/OGRAdapters/otbGeometriesToGeometriesFilter.cxx
@@ -70,15 +70,19 @@ struct ProcessVisitor : boost::static_visitor<>
     assert(destination && "can't filter to a nil datasource");
     // std::cout << "G2GF: Process Visitor: DS("<<source->ogr().GetName()<<") -> DS("<<destination->ogr().GetName()<<") ...\n";
     for (otb::ogr::DataSource::const_iterator b = source->begin(), e = source->end()
-; b != e
-; ++b
+      ; b != e
+      ; ++b
     )
       {
       otb::ogr::Layer const& sourceLayer = *b;
       assert(sourceLayer && "unexpected nil source layer");
       // std::cout << "source layer name:" << sourceLayer.GetName() << "\n";
       otb::ogr::Layer destLayer = destination->CreateLayer(
-        sourceLayer.GetName(), 0, sourceLayer.GetGeomType());
+        sourceLayer.GetName(),
+        m_filter.DoDefineNewLayerSpatialReference(sourceLayer),
+        m_filter.DoDefineNewLayerGeometryType(sourceLayer),
+        otb::ogr::StringListConverter(m_filter.DoDefineNewLayerOptions(sourceLayer)).to_ogr()
+        );
       // std::cout << "layer created!\n";
       m_filter.DoProcessLayer(sourceLayer, destLayer);
       }
@@ -148,6 +152,8 @@ void otb::GeometriesToGeometriesFilter::GenerateData(void )
 {
   // std::cout << "G2GF::GenerateData\n";
   this->AllocateOutputs();
+  this->FinalizeInitialisation();
+
   InputGeometriesType::ConstPointer  input  = this->GetInput();
   // assert(input && "Cann't filter to a nil geometries set");
   OutputGeometriesType::Pointer      output = this->GetOutput();
diff --git a/Code/UtilitiesAdapters/OGRAdapters/otbGeometriesToGeometriesFilter.h b/Code/UtilitiesAdapters/OGRAdapters/otbGeometriesToGeometriesFilter.h
index ae73da1c9c1f7e7c342effd1c81b25249d84b446..2354c8895534b251d42e88aea263baf7fb1713f2 100644
--- a/Code/UtilitiesAdapters/OGRAdapters/otbGeometriesToGeometriesFilter.h
+++ b/Code/UtilitiesAdapters/OGRAdapters/otbGeometriesToGeometriesFilter.h
@@ -71,6 +71,10 @@ private:
   void Process(OutputGeometriesType &inout);
   void Process(InputGeometriesType const& source, OutputGeometriesType &destination);
   virtual void DoProcessLayer(ogr::Layer const& source, ogr::Layer & destination) const=0;
+  virtual OGRSpatialReference*     DoDefineNewLayerSpatialReference(ogr::Layer const& source) const { return 0; }
+  virtual OGRwkbGeometryType       DoDefineNewLayerGeometryType(ogr::Layer const& source) const { return source.GetGeomType(); }
+  virtual std::vector<std::string> DoDefineNewLayerOptions(ogr::Layer const& source) const { return std::vector<std::string>(); }
+  virtual void FinalizeInitialisation() {}
   friend struct ::ProcessVisitor;
   };
 
@@ -85,6 +89,7 @@ struct TransformationFunctorDispatcher<TransformationFunctor, ogr::Layer>
   {
   typedef typename TransformationFunctor::TransformedElementType TransformedElementType;
   BOOST_MPL_ASSERT((boost::is_same<ogr::Layer, TransformedElementType>));
+  TransformationFunctorDispatcher() { }
   TransformationFunctorDispatcher(TransformationFunctor functor) : m_functor(functor){ }
   void operator()(ogr::Layer const& in, ogr::Layer & out) const
     {
@@ -94,6 +99,7 @@ struct TransformationFunctorDispatcher<TransformationFunctor, ogr::Layer>
     {
     m_functor(inout);
     }
+  TransformationFunctor * operator->() { return &m_functor; }
 private:
   TransformationFunctor m_functor;
   };
@@ -104,6 +110,7 @@ struct TransformationFunctorDispatcher<TransformationFunctor, OGRGeometry>
   {
   typedef typename TransformationFunctor::TransformedElementType TransformedElementType;
   BOOST_MPL_ASSERT((boost::is_same<OGRGeometry, TransformedElementType>));
+  TransformationFunctorDispatcher() { }
   TransformationFunctorDispatcher(TransformationFunctor functor) : m_functor(functor){ }
 
   void operator()(ogr::Layer const& in, ogr::Layer & out) const
@@ -137,6 +144,7 @@ struct TransformationFunctorDispatcher<TransformationFunctor, OGRGeometry>
       inout.SetFeature(feat);
       }
     }
+  TransformationFunctor * operator->() { return &m_functor; }
 private:
   TransformationFunctor m_functor;
   };
diff --git a/Code/UtilitiesAdapters/OGRAdapters/otbGeometriesToGeometriesFilter.txx b/Code/UtilitiesAdapters/OGRAdapters/otbGeometriesToGeometriesFilter.txx
index 76f76ab4af36e912a13c6792a66e80111ff289fa..f7c1230d6050a4f1bff54598d685de49245f51f9 100644
--- a/Code/UtilitiesAdapters/OGRAdapters/otbGeometriesToGeometriesFilter.txx
+++ b/Code/UtilitiesAdapters/OGRAdapters/otbGeometriesToGeometriesFilter.txx
@@ -27,7 +27,6 @@
 template <class TransformationFunctor>
 inline
 otb::DefaultGeometriesToGeometriesFilter<TransformationFunctor>::DefaultGeometriesToGeometriesFilter()
-: m_TransformationFunctor(TransformationFunctor())
 {}
 
 template <class TransformationFunctor>
diff --git a/Code/UtilitiesAdapters/OGRAdapters/otbImageReference.h b/Code/UtilitiesAdapters/OGRAdapters/otbImageReference.h
new file mode 100644
index 0000000000000000000000000000000000000000..78978b278cf7b9fe59a2ab99413889e34e1174c8
--- /dev/null
+++ b/Code/UtilitiesAdapters/OGRAdapters/otbImageReference.h
@@ -0,0 +1,171 @@
+/*=========================================================================
+
+  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 __otbImageReference_h
+#define __otbImageReference_h
+
+#include "itkVector.h"
+#include "itkPoint.h"
+#include "itkMacro.h"
+
+namespace otb
+{
+namespace ogr
+{
+/**\ingroup gGeometry
+ * \class ImageReference
+ * \todo See how mix it with the \c otb::ogr::DataSource wrapper as it was
+ * with \c VectorData.
+ * \since OTB v 3.14.0
+ */
+template <typename TPrecision> class ImageReference
+{
+public:
+  typedef TPrecision PrecisionType;
+  enum { Dimension = 2 };
+  /**\name Standard ITK typedefs */
+  //@{
+  itkTypeMacro(ImageReference, void);
+  bool GetDebug() const
+    {
+    return m_holder.GetDebug();
+    }
+  //@}
+  /**\name Template-parameters typedefs */
+  //@{
+  typedef itk::Vector<PrecisionType, 2> SpacingType;
+  typedef itk::Point<PrecisionType, 2>  OriginType;
+  typedef itk::Point<PrecisionType, 2>  PointType;
+  //@}
+
+  /** Default constructor.
+   * \post <tt>m_Spacing = {1,1}</tt>
+   * \post <tt>m_Origin = {0,0}</tt>
+   */
+  ImageReference(itk::Object const& holder)
+    : m_holder(holder)
+    {
+    m_Spacing.Fill(1);
+    m_Origin.Fill(0);
+    }
+  /** Init constructor.
+   * \post <tt>m_Spacing = spacing</tt>
+   * \post <tt>m_Origin = origin</tt>
+   */
+  ImageReference(SpacingType const& spacing, OriginType const& origin, itk::Object const& holder)
+    : m_holder(holder) , m_Spacing(spacing), m_Origin(origin)
+    {
+    }
+
+  void Modified() const
+    {
+    m_holder.Modified();
+    }
+
+  /**\name Origin property
+   * Represents the origin of the geometries in the image coordinates system.
+   */
+  //@{
+  itkGetConstReferenceMacro(Origin, OriginType);     //!< Origin getter.
+  itkSetMacro(Origin, OriginType);                   //!< Origin setter.
+  void SetOrigin(const TPrecision origin[Dimension]) //!< Origin setter.
+    {
+    const OriginType p(origin);
+    this->SetOrigin(p);
+    }
+  //@}
+
+  /**\name Spacing property
+   * Spacing of the geometries to put in the corresponding image coordinates.
+   */
+  //@{
+  itkGetConstReferenceMacro(Spacing, SpacingType);         //!< Spacing getter.
+  void SetSpacing(const SpacingType& spacing)              //!< Spacing setter.
+    {
+    // itkDebugMacro("setting Spacing to " << spacing);
+    if (this->m_Spacing != spacing)
+      {
+      this->m_Spacing = spacing;
+      this->Modified();
+      }
+    }
+  void SetSpacing(const TPrecision spacing[Dimension]) //!< Spacing setter.
+    {
+    const SpacingType s(spacing);
+    this->SetSpacing(s);
+    }
+  //@}
+
+  /**
+   * Projects a point from the Data Source coordinates system to the image
+   * coordinates system.
+   * \param[in] point  point in Data Source coordinates system
+   * \param[out] physicalPoint  point in the image coordinates system.
+   * \throw None
+   */
+  void TransformPointToPhysicalPoint(const PointType& point, PointType& physicalPoint) const
+    {
+    for (size_t i=0; i!=Dimension; ++i)
+      physicalPoint[i] = point[i] * m_Spacing[i] + m_Origin[i];
+    }
+
+  /**
+   * Projects a point from the Data Source coordinates system to the image
+   * coordinates system.
+   * \param[in] point  point in Data Source coordinates system
+   * \return the point projected in the image coordinates system.
+   * \throw None
+   */
+  void TransformPointToPhysicalPoint(const PointType& point) const
+    {
+    // why no loop on VDimension ?
+    PointType physicalPoint;
+    for (size_t i=0; i!=Dimension; ++i)
+      physicalPoint[i] = point[i] * m_Spacing[i] + m_Origin[i];
+    return physicalPoint;
+    }
+
+  /**
+   * Assignment operator.
+   * \param[in] rhs source data to be copied.
+   * \throw None
+   * \internal
+   * Required because of the hack to provide a \c GetDebug() function which is
+   * required by \c itkTypeMacro.
+   */
+  ImageReference& operator=(ImageReference const& rhs)
+    {
+    m_Spacing = rhs.m_Spacing;
+    m_Origin  = rhs.m_Origin;
+    return *this;
+    }
+
+private:
+  itk::Object     const& m_holder;
+  SpacingType            m_Spacing;
+  OriginType             m_Origin;
+};
+
+} // ogr namespace
+
+} // end namespace otb
+
+#ifndef OTB_MANUAL_INSTANTIATION
+// #include "otbImageReference.txx"
+#endif
+
+#endif // __otbImageReference_h
diff --git a/Code/UtilitiesAdapters/OGRAdapters/otbOGRDataSourceWrapper.cxx b/Code/UtilitiesAdapters/OGRAdapters/otbOGRDataSourceWrapper.cxx
index 54ccbc270a8d372bab8219713ab79f84a78530e7..be40fbd4436a2e6e08f8c9fa98572cc4f7f06f53 100644
--- a/Code/UtilitiesAdapters/OGRAdapters/otbOGRDataSourceWrapper.cxx
+++ b/Code/UtilitiesAdapters/OGRAdapters/otbOGRDataSourceWrapper.cxx
@@ -256,7 +256,7 @@ otb::ogr::Layer otb::ogr::DataSource::CreateLayer(
       << "> in the OGRDataSource file <" << m_DataSource->GetName()
       <<">: " << CPLGetLastErrorMsg());
     }
-  Layer l(ol);
+  Layer l(ol, this);
   return l;
 }
 
@@ -275,7 +275,7 @@ otb::ogr::Layer otb::ogr::DataSource::CopyLayer(
       << "> in the OGRDataSource file <" << m_DataSource->GetName()
       <<">: " << CPLGetLastErrorMsg());
     }
-  Layer l(ol);
+  Layer l(ol, this);
   return l;
 }
 
@@ -310,7 +310,7 @@ otb::ogr::Layer otb::ogr::DataSource::GetLayerChecked(size_t i)
     itkExceptionMacro( << "Unexpected error: cannot fetch " << i << "th layer in the OGRDataSource <"
       << m_DataSource->GetName() << ">: " << CPLGetLastErrorMsg());
     }
-    return otb::ogr::Layer(layer_ptr);
+    return otb::ogr::Layer(layer_ptr, this);
 }
 
 OGRLayer* otb::ogr::DataSource::GetLayerUnchecked(size_t i)
@@ -324,7 +324,7 @@ otb::ogr::Layer otb::ogr::DataSource::GetLayer(std::string const& name)
 {
   assert(m_DataSource && "Datasource not initialized");
   OGRLayer * layer_ptr = m_DataSource->GetLayerByName(name.c_str());
-  return otb::ogr::Layer(layer_ptr);
+  return otb::ogr::Layer(layer_ptr, this);
 }
 
 
@@ -338,7 +338,7 @@ otb::ogr::Layer otb::ogr::DataSource::GetLayerChecked(std::string const& name)
       << "> in the OGRDataSource <" << m_DataSource->GetName() << ">: "
       << CPLGetLastErrorMsg());
     }
-  return otb::ogr::Layer(layer_ptr);
+  return otb::ogr::Layer(layer_ptr, this);
 }
 
 int otb::ogr::DataSource::GetLayersCount() const
@@ -364,7 +364,7 @@ otb::ogr::Layer otb::ogr::DataSource::ExecuteSQL(
     // Cannot use the deleter made for result sets obtained from
     // OGRDataSource::ExecuteSQL because it checks for non-nullity....
     // *sigh*
-    return otb::ogr::Layer(0);
+    return otb::ogr::Layer(0, 0);
 #endif
     }
   return otb::ogr::Layer(layer_ptr, *m_DataSource);
diff --git a/Code/UtilitiesAdapters/OGRAdapters/otbOGRDataSourceWrapper.h b/Code/UtilitiesAdapters/OGRAdapters/otbOGRDataSourceWrapper.h
index 78f976d352ef83cf638eb32303096d1e5f7bbbab..0745c971392a91cc94a9bf64c57f0bf899da45f4 100644
--- a/Code/UtilitiesAdapters/OGRAdapters/otbOGRDataSourceWrapper.h
+++ b/Code/UtilitiesAdapters/OGRAdapters/otbOGRDataSourceWrapper.h
@@ -27,8 +27,6 @@
 #include <boost/type_traits/is_const.hpp>
 #include <boost/noncopyable.hpp>
 
-#include "itkVector.h"
-#include "itkPoint.h"
 #include "itkDataObject.h"
 #include "itkMacro.h" // itkNewMacro
 #include "itkObjectFactory.h" // that should have been included by itkMacro.h
@@ -42,112 +40,6 @@ class OGRGeometry;
 // #include "ogr_core.h" // OGRwkbGeometryType, included from Layer
 
 namespace otb { namespace ogr {
-/**\ingroup gGeometry
- * \class ImageReference
- * \todo See how mix it with the \c otb::ogr::DataSource wrapper as it was
- * with \c VectorData.
- * \since OTB v 3.14.0
- */
-template <typename TPrecision> class ImageReference
-  {
-public:
-  typedef TPrecision PrecisionType;
-  enum { Dimension = 2 };
-  /**\name Standard ITK typedefs */
-  //@{
-  //@}
-  /**\name Template-parameters typedefs */
-  //@{
-  typedef itk::Vector<PrecisionType, 2> SpacingType;
-  typedef itk::Point<PrecisionType, 2>  OriginType;
-  typedef itk::Point<PrecisionType, 2>  PointType;
-  //@}
-
-  /** Default constructor.
-   * \post <tt>m_Spacing = {1,1}</tt>
-   * \post <tt>m_Origin = {0,0}</tt>
-   */
-  ImageReference()
-    {
-    m_Spacing.Fill(1);
-    m_Origin.Fill(0);
-    }
-  /** Init constructor.
-   * \post <tt>m_Spacing = spacing</tt>
-   * \post <tt>m_Origin = origin</tt>
-   */
-  ImageReference(SpacingType const& spacing, OriginType const& origin)
-    : m_Spacing(spacing), m_Origin(origin)
-    {
-    }
-
-  /**\name Origin property
-   * Represents the origin of the geometries in the image coordinates system.
-   */
-  //@{
-  itkGetConstReferenceMacro(Origin, OriginType);     //!< Origin getter.
-  itkSetMacro(Origin, OriginType);                   //!< Origin setter.
-  void SetOrigin(const TPrecision origin[Dimension]) //!< Origin setter.
-    {
-    const OriginType p(origin);
-    this->SetOrigin(p);
-    }
-  //@}
-
-  /**\name Spacing property
-   * Spacing of the geometries to put in the corresponding image coordinates.
-   */
-  //@{
-  itkGetConstReferenceMacro(Spacing, SpacingType);         //!< Spacing getter.
-  void SetSpacing(const SpacingType& spacing)              //!< Spacing setter.
-    {
-    itkDebugMacro("setting Spacing to " << spacing);
-    if (this->m_Spacing != spacing)
-      {
-      this->m_Spacing = spacing;
-      this->Modified();
-      }
-    }
-  void SetSpacing(const TPrecision spacing[Dimension]) //!< Spacing setter.
-    {
-    const SpacingType s(spacing);
-    this->SetSpacing(s);
-    }
-  //@}
-
-  /**
-   * Projects a point from the Data Source coordinates system to the image
-   * coordinates system.
-   * \param[in] point  point in Data Source coordinates system
-   * \param[out] physicalPoint  point in the image coordinates system.
-   * \throw None
-   */
-  void TransformPointToPhysicalPoint(const PointType& point, PointType& physicalPoint) const
-    {
-    for (size_t i=0; i!=Dimension; ++i)
-      physicalPoint[i] = point[i] * m_Spacing[i] + m_Origin[i];
-    }
-
-  /**
-   * Projects a point from the Data Source coordinates system to the image
-   * coordinates system.
-   * \param[in] point  point in Data Source coordinates system
-   * \return the point projected in the image coordinates system.
-   * \throw None
-   */
-  void TransformPointToPhysicalPoint(const PointType& point) const
-    {
-    // why no loop on VDimension ?
-    PointType physicalPoint;
-    for (size_t i=0; i!=Dimension; ++i)
-      physicalPoint[i] = point[i] * m_Spacing[i] + m_Origin[i];
-    return physicalPoint;
-    }
-private:
-  SpacingType                 m_Spacing;
-  OriginType                  m_Origin;
-  };
-
 /**\ingroup gGeometry
  * \class DataSource
  * \brief Collection of geometric objects.
diff --git a/Code/UtilitiesAdapters/OGRAdapters/otbOGRDataSourceWrapper.txx b/Code/UtilitiesAdapters/OGRAdapters/otbOGRDataSourceWrapper.txx
index 5f336bab58b9824943bd9fccbc22a30e4b0a9a30..f56d3d5283bb3af4f29ab73f0dc5b10c17697610 100644
--- a/Code/UtilitiesAdapters/OGRAdapters/otbOGRDataSourceWrapper.txx
+++ b/Code/UtilitiesAdapters/OGRAdapters/otbOGRDataSourceWrapper.txx
@@ -50,7 +50,7 @@ otb::ogr::Layer otb::ogr::DataSource::GetLayer(size_t i)
   assert(int(i) < GetLayersCount() && "Out-of-range index");
   OGRLayer * layer_ptr = GetLayerUnchecked(i);
   assert(layer_ptr && "No layer returned by OGR");
-  return otb::ogr::Layer(layer_ptr);
+  return otb::ogr::Layer(layer_ptr, this);
 }
 
 inline
@@ -123,7 +123,7 @@ Value otb::ogr::DataSource::layer_iter<Value>::dereference() const
   assert(m_DataSource
     && int(m_index) < m_DataSource->GetLayersCount()
     && "cannot dereference past end()");
-  return Value(m_DataSource->GetLayerUnchecked(m_index));
+  return Value(m_DataSource->GetLayerUnchecked(m_index), const_cast <DataSource*>(m_DataSource));
 }
 
 
diff --git a/Code/UtilitiesAdapters/OGRAdapters/otbOGRGeometriesVisitor.h b/Code/UtilitiesAdapters/OGRAdapters/otbOGRGeometriesVisitor.h
new file mode 100644
index 0000000000000000000000000000000000000000..1eec99f88921fdafe2ca2dd4ac8707b4a097726f
--- /dev/null
+++ b/Code/UtilitiesAdapters/OGRAdapters/otbOGRGeometriesVisitor.h
@@ -0,0 +1,74 @@
+/*=========================================================================
+
+  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 __otbOGRGeometriesVisitor_h
+#define __otbOGRGeometriesVisitor_h
+
+#include <boost/mpl/assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include "ogr_geometry.h"
+
+namespace otb
+{
+namespace ogr
+{
+template <typename Tin, typename Tout>
+struct propagate_const
+{
+typedef Tout type;
+};
+template <typename Tin, typename Tout>
+struct propagate_const<Tin const, Tout>
+{
+typedef typename boost::add_const<Tout>::type type;
+};
+
+#define TRY_APPLY(TYPE, geometry, functor) \
+if (typename propagate_const<TGeometry, TYPE>::type * dc = dynamic_cast<typename propagate_const<TGeometry, TYPE>::type*>(geometry))\
+{\
+  return functor(dc); \
+}
+
+
+template <typename TResult, class TGeometry, typename TFunctor>
+TResult apply(TGeometry * geometry, TFunctor functor)
+{
+  BOOST_MPL_ASSERT((boost::is_same<OGRGeometry, typename boost::remove_const<TGeometry>::type >));
+  TRY_APPLY(OGRPoint, geometry, functor)
+    else TRY_APPLY(OGRLinearRing, geometry, functor)
+    else TRY_APPLY(OGRLineString, geometry, functor)
+    // else TRY_APPLY(OGRCurve, geometry, functor)
+    else TRY_APPLY(OGRPolygon, geometry, functor)
+    // else TRY_APPLY(OGRSurface, geometry, functor)
+    else TRY_APPLY(OGRMultiLineString, geometry, functor)
+    else TRY_APPLY(OGRMultiPoint, geometry, functor)
+    else TRY_APPLY(OGRMultiPolygon, geometry, functor)
+    else TRY_APPLY(OGRGeometryCollection, geometry, functor)
+      {
+      // functor(geometry);
+      }
+}
+} // ogr namespace
+
+} // end namespace otb
+
+#ifndef OTB_MANUAL_INSTANTIATION
+// #include "otbOGRGeometriesVisitor.txx"
+#endif
+
+#endif // __otbOGRGeometriesVisitor_h
diff --git a/Code/UtilitiesAdapters/OGRAdapters/otbOGRLayerWrapper.cxx b/Code/UtilitiesAdapters/OGRAdapters/otbOGRLayerWrapper.cxx
index cbbe9192cc4d9e7315773d987f0daf52d66e9c18..37460f6b653224f14091d6279d3bcd4ffe5e149a 100644
--- a/Code/UtilitiesAdapters/OGRAdapters/otbOGRLayerWrapper.cxx
+++ b/Code/UtilitiesAdapters/OGRAdapters/otbOGRLayerWrapper.cxx
@@ -26,6 +26,8 @@
 #include <boost/foreach.hpp>
 #include "ogrsf_frmts.h" // OGRDataSource & OGRLayer
 
+#include "otbOGRDataSourceWrapper.h"
+
 /*===========================================================================*/
 /*======================[ Construction & Destruction ]=======================*/
 /*===========================================================================*/
@@ -42,8 +44,9 @@ namespace  { // Anonymous namespace
 } // Anonymous namespace
 
 
-otb::ogr::Layer::Layer(OGRLayer* layer)
+otb::ogr::Layer::Layer(OGRLayer* layer, DataSourcePtr datasource)
 : m_Layer(layer, LeaveAloneDeleter())
+, m_DataSource(datasource)
 {
 }
 
@@ -330,3 +333,12 @@ bool otb::ogr::operator==(Layer const& lhs, Layer const& rhs)
   const bool equal = lhs.m_Layer.get() == rhs.m_Layer.get();
   return equal;
 }
+
+itk::MetaDataDictionary & otb::ogr::Layer::GetMetaDataDictionary()
+{
+  if (!m_DataSource)
+    {
+    itkGenericExceptionMacro(<<"Cannot acces metadata dictionary from a layer constructed with an SQL request.");
+    }
+  return m_DataSource->GetMetaDataDictionary();
+}
diff --git a/Code/UtilitiesAdapters/OGRAdapters/otbOGRLayerWrapper.h b/Code/UtilitiesAdapters/OGRAdapters/otbOGRLayerWrapper.h
index 9da06e1acbc935380a0f71bca3ac7e0dd2c18d4f..64d77f92a7fc23dbb422372be233da6efc78b00a 100644
--- a/Code/UtilitiesAdapters/OGRAdapters/otbOGRLayerWrapper.h
+++ b/Code/UtilitiesAdapters/OGRAdapters/otbOGRLayerWrapper.h
@@ -32,8 +32,14 @@ class OGRDataSource;
 class OGRGeometry;
 class OGRFeatureDefn;
 
-namespace otb { namespace ogr {
+namespace itk
+{
+class MetaDataDictionary;
+} // itk namespace
+
 
+namespace otb { namespace ogr {
+class DataSource;
 class Layer;
 
 /**\ingroup gGeometry
@@ -64,16 +70,20 @@ bool operator==(Layer const& lhs, Layer const& rhs);
 class Layer
   {
 public:
-  /**\name ITK class typedefs */
+  /**\name ITK standard definitions */
   //@{
   typedef Layer                         Self;
+  itkTypeMacro(Layer, void);
   //@}
 
+  typedef itk::SmartPointer<DataSource> DataSourcePtr;
+
   /**\name Construction */
   //@{
   /**
    * Init constructor with a layer owned by a DataSource.
    * \param layer \c OGRLayer instance that is owned by a DataSource.
+   * \param datasource Pointer to the actual data source.
    * \throw None
    * On destruction of the proxy class, the internal \c OGRLayer is left alone.
    *
@@ -81,13 +91,15 @@ public:
    * is deleted, the layer won't be usable anymore. Unfortunatelly, there is no
    * mean to report this to this layer proxy.
    */
-  explicit Layer(OGRLayer* layer);
+  Layer(OGRLayer* layer, DataSourcePtr datasource);
 
   /**
    * Init constructor for layers that need to be released.
    * \param layer  \c OGRLayer owned by the client code.
    * \param sourceInChargeOfLifeTime  reference to the actual \c OGRDataSource
    * that knows how to release the layer.
+   * \post In this case, \c m_datasource is left null: we suppose (for now, that
+   * the layer won't need access to the datasource meta-information).
    *
    * \throw None
    * \internal
@@ -462,6 +474,12 @@ public:
   OGRwkbGeometryType GetGeomType() const;
 
   friend bool otb::ogr::operator==(Layer const& lhs, Layer const& rhs);
+
+  /**\name Meta data dictionary */
+  //@{
+  itk::MetaDataDictionary      & GetMetaDataDictionary();
+  itk::MetaDataDictionary const& GetMetaDataDictionary() const;
+  //@}
 private:
   /**
    * Internal encapsulation of \c OGRLayer::GetNextFeature().
@@ -481,6 +499,11 @@ private:
    * to correctly release the layer.
    */
   boost::shared_ptr<OGRLayer> m_Layer;
+
+  /** Related DataSource.
+   * Needed to acces OTB meta informations.
+   */
+  DataSourcePtr m_DataSource;
   };
 
 inline bool operator!=(Layer const& lhs, Layer const& rhs)
diff --git a/Examples/Filtering/CMakeLists.txt b/Examples/Filtering/CMakeLists.txt
index e59c88e32f9858cb39a4d9b3bccbca41853133e6..655f8b3f5ab446ac27a7cfe13dabeabde547f4da 100644
--- a/Examples/Filtering/CMakeLists.txt
+++ b/Examples/Filtering/CMakeLists.txt
@@ -63,6 +63,9 @@ ITKCommon ITKBasicFilters)
 ADD_EXECUTABLE(GeometriesFilter GeometriesFilter.cxx)
 TARGET_LINK_LIBRARIES(GeometriesFilter OTBOGRAdapters)
 
+ADD_EXECUTABLE(GeometriesChangeSpatialReference GeometriesChangeSpatialReference.cxx)
+TARGET_LINK_LIBRARIES(GeometriesChangeSpatialReference OTBOGRAdapters)
+
 IF(OTB_USE_MAPNIK)
 ADD_EXECUTABLE(RasterizationExample RasterizationExample.cxx)
 TARGET_LINK_LIBRARIES(RasterizationExample OTBCommon OTBIO OTBBasicFilters)
diff --git a/Examples/Filtering/GeometriesChangeSpatialReference.cxx b/Examples/Filtering/GeometriesChangeSpatialReference.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..53dcf25ad3db8aad6725e54799adfba7c131c4e0
--- /dev/null
+++ b/Examples/Filtering/GeometriesChangeSpatialReference.cxx
@@ -0,0 +1,139 @@
+/*=========================================================================
+
+  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.
+
+=========================================================================*/
+
+/*===========================================================================*/
+/*===============================[ Includes ]================================*/
+/*===========================================================================*/
+#include "otbGeometriesToGeometriesFilter.h"
+#include <string>
+#include <iostream>
+#include "otbOGRDataSourceWrapper.h"
+#include "otbGeometriesSet.h"
+#include "otbOGRGeometryWrapper.h"
+
+/*===========================================================================*/
+/*=========================[ Reprojection functor ]==========================*/
+/*===========================================================================*/
+namespace internal
+{
+struct CoordTranfoDeleter
+{
+  void operator()(OGRCoordinateTransformation *p);
+};
+} // internal namespace
+
+struct ReprojectTransformationFunctor
+{
+  typedef OGRGeometry TransformedElementType;
+
+  otb::ogr::UniqueGeometryPtr operator()(OGRGeometry const* in) const;
+  void setSpatialReferences(OGRSpatialReference & in, OGRSpatialReference & out);
+private:
+  boost::interprocess::unique_ptr<OGRCoordinateTransformation, internal::CoordTranfoDeleter> m_reprojector;
+};
+
+
+void internal::CoordTranfoDeleter::operator()(OGRCoordinateTransformation *p)
+{
+  OCTDestroyCoordinateTransformation(p);
+}
+
+otb::ogr::UniqueGeometryPtr
+ReprojectTransformationFunctor::operator()(OGRGeometry const* in) const
+{
+  otb::ogr::UniqueGeometryPtr out(in ? in->clone() : 0);
+  if (out)
+    {
+    const OGRErr err = out->transform(m_reprojector.get());
+    if (!err != OGRERR_NONE)
+      {
+      itkGenericExceptionMacro(<< "Cannot reproject a geometry: " << CPLGetLastErrorMsg());
+      }
+    }
+  else
+    return boost::move(out);
+}
+
+void ReprojectTransformationFunctor::setSpatialReferences(
+  OGRSpatialReference & in, OGRSpatialReference & out)
+{
+  m_reprojector.reset(OGRCreateCoordinateTransformation(&in, &out));
+}
+
+/*===========================================================================*/
+/*=================================[ main ]==================================*/
+/*===========================================================================*/
+typedef otb::DefaultGeometriesToGeometriesFilter<ReprojectTransformationFunctor> FilterType;
+
+int main (int argc, char **argv)
+{
+  if (argc < 2)
+    {
+    std::cerr << argv[0] << " inputGeometriesFile [outputGeometriesFile]" << std::endl;
+    return EXIT_FAILURE;
+    }
+  try
+    {
+    const bool workingInplace = argc==2;
+    const bool outputIsStdout = !workingInplace && !strcmp(argv[2], "-");
+
+    const std::string inputFile = argv[1];
+    const std::string outputFile = workingInplace ? argv[1] : argv[2];
+
+    otb::ogr::DataSource::Pointer input = otb::ogr::DataSource::New(
+      inputFile,
+      workingInplace ? otb::ogr::DataSource::Modes::write : otb::ogr::DataSource::Modes::read);
+
+    otb::ogr::DataSource::Pointer output
+      = workingInplace ? input
+      : outputIsStdout ? 0
+      :                  otb::ogr::DataSource::New( outputFile, otb::ogr::DataSource::Modes::write);
+    std::cout << "input: " << input -> ogr().GetName() << " should be: " << inputFile << "\n";
+    if (output)
+      {
+      std::cout << "output: " << output -> ogr().GetName() << " should be: " << outputFile << "\n";
+      }
+    // std::cout << "\n";
+
+    FilterType::Pointer filter = FilterType::New();
+    if (!workingInplace)
+      {
+      otb::GeometriesSet::Pointer in_set = otb::GeometriesSet::New(input);
+      filter->SetInput(in_set);
+      }
+    if (output)
+      {
+      otb::GeometriesSet::Pointer out_set = otb::GeometriesSet::New(output);
+      filter->SetOutput(out_set);
+      out_set->Update();
+      }
+    else
+      {
+      filter->UpdateOutputData(0);
+      assert(filter->GetOutput() && "output not set");
+      filter->GetOutput()->Print(std::cout, 0);
+      }
+
+    return EXIT_SUCCESS;
+    }
+  catch (std::exception const& e)
+    {
+    std::cerr << e.what() << "\n";
+    }
+  return EXIT_FAILURE;
+}
diff --git a/Examples/Filtering/GeometriesFilter.cxx b/Examples/Filtering/GeometriesFilter.cxx
index b05aea74a471e617659630ecf8daaca48112f0b6..a1c84487cafd1af15e42586f56454687a9684bb0 100644
--- a/Examples/Filtering/GeometriesFilter.cxx
+++ b/Examples/Filtering/GeometriesFilter.cxx
@@ -26,7 +26,7 @@
 #include "otbGeometriesSet.h"
 
 /*===========================================================================*/
-/*==============================[ other stuff ]==============================*/
+/*=============================[ SwapXYFunctor ]=============================*/
 /*===========================================================================*/
 struct SwapXYFunctor
 {
@@ -46,12 +46,16 @@ struct SwapXYFunctor
     }
 };
 
+/*===========================================================================*/
+/*=================================[ main ]==================================*/
+/*===========================================================================*/
+typedef otb::DefaultGeometriesToGeometriesFilter<SwapXYFunctor> FilterType;
+
 int main (int argc, char **argv)
 {
   if (argc < 2)
     {
-    std::cerr << " inputGeometriesFile [outputGeometriesFile]" << std::endl;
-    // if outputGeometriesFile == "-", output == stdout
+    std::cerr << argv[0] << " inputGeometriesFile [outputGeometriesFile]" << std::endl;
     return EXIT_FAILURE;
     }
   try
@@ -77,8 +81,7 @@ int main (int argc, char **argv)
       }
     // std::cout << "\n";
 
-    otb::DefaultGeometriesToGeometriesFilter<SwapXYFunctor>::Pointer filter
-      = otb::DefaultGeometriesToGeometriesFilter<SwapXYFunctor>::New();
+    FilterType::Pointer filter = FilterType::New();
     if (!workingInplace)
       {
       otb::GeometriesSet::Pointer in_set = otb::GeometriesSet::New(input);
diff --git a/Examples/Projections/CMakeLists.txt b/Examples/Projections/CMakeLists.txt
index 6acebc2a08e1fda9d915b60ddb8d18a5e0769bac..e5ccd6763ea856de49ca9aca973be2577fd6a9f8 100644
--- a/Examples/Projections/CMakeLists.txt
+++ b/Examples/Projections/CMakeLists.txt
@@ -31,6 +31,9 @@ ENDIF( OTB_USE_CURL )
 ADD_EXECUTABLE(VectorDataProjectionExample VectorDataProjectionExample.cxx )
 TARGET_LINK_LIBRARIES(VectorDataProjectionExample OTBProjections OTBCommon OTBIO)
 
+ADD_EXECUTABLE(GeometriesProjection GeometriesProjection.cxx )
+TARGET_LINK_LIBRARIES(GeometriesProjection OTBProjections OTBOGRAdapters)
+
 ADD_EXECUTABLE(VectorDataExtractROIExample VectorDataExtractROIExample.cxx )
 TARGET_LINK_LIBRARIES(VectorDataExtractROIExample OTBProjections OTBCommon OTBIO)
 
@@ -113,6 +116,18 @@ ADD_TEST(prTeVectorDataProjectionExampleTest ${EXE_TESTS}
 )
 ENDIF(OTB_DATA_USE_LARGEINPUT)
 
+IF(OTB_DATA_USE_LARGEINPUT)
+ADD_TEST(prTeGeometriesProjectionTest ${EXE_TESTS}
+        --compare-ogr ${TOL}
+        ${BASELINE}/vectorDataProjectionExample.shp
+        ${TEMP}/geometriesProjectionExample.shp
+    GeometriesProjectionTest
+        ${INPUTDATA}/Capitole-Shadows.kml
+        ${INPUTLARGEDATA}/QUICKBIRD/TOULOUSE/000000128955_01_P001_PAN/02APR01105228-P1BS-000000128955_01_P001.TIF
+            ${TEMP}/geometriesProjectionExample.shp
+)
+ENDIF(OTB_DATA_USE_LARGEINPUT)
+
 IF(OTB_DATA_USE_LARGEINPUT)
 #TODO change the example by using a SPOT4 roamnia
 ADD_TEST(prTeEstimateRPCSensorModelExampleTest ${EXE_TESTS}
diff --git a/Examples/Projections/GeometriesProjection.cxx b/Examples/Projections/GeometriesProjection.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..b0571f4bd29269f2f6cb7a8375f09759ab44c4ca
--- /dev/null
+++ b/Examples/Projections/GeometriesProjection.cxx
@@ -0,0 +1,163 @@
+/*=========================================================================
+
+  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.
+
+=========================================================================*/
+
+// Software Guide : BeginLatex
+//
+// Let's assume that you have a KML file (hence in geographical coordinates)
+// that you would like to superpose to some image with a specific map projection.
+// Of course, you could use the handy ogr2ogr tool to do that, but it won't
+// integrate so seamlessly into your OTB application.
+//
+// You can also suppose that the image on which you want to superpose
+// the data is not in a specific map projection but a raw image from a
+// particular sensor.  Thanks to OTB, the same code below will be able
+// to do the appropriate conversion.
+//
+// This example demonstrates the use of the
+// \doxygen{otb}{GeometriesProjectionFilter}.
+//
+// Software Guide : EndLatex
+
+#include "otbGeometriesProjectionFilter.h"
+#include "otbGeometriesSet.h"
+// #include "otbGeometriesFileReader.h"
+// #include "otbGeometriesFileWriter.h"
+
+#include "otbImage.h"
+#include "otbImageFileReader.h"
+
+int main(int argc, char* argv[])
+{
+
+  if (argc < 4)
+    {
+    std::cerr << argv[0] <<
+    " <input vector filename> <input image name> <output vector filename>\n";
+
+    return EXIT_FAILURE;
+    }
+
+  // Software Guide : BeginLatex
+  //
+  // Declare the vector data type that you would like to use in your
+  // application.
+  //
+  // Software Guide : EndLatex
+
+  // Software Guide : BeginCodeSnippet
+  typedef otb::GeometriesSet InputGeometriesType;
+  typedef otb::GeometriesSet OutputGeometriesType;
+  // Software Guide : EndCodeSnippet
+
+  // Software Guide : BeginLatex
+  //
+  // Declare and instantiate the vector data reader:
+  // \doxygen{otb}{GeometriesFileReader}. The call to the
+  // \code{UpdateOutputInformation()} method fill up the header information.
+  //
+  // Software Guide : EndLatex
+
+  // Software Guide : BeginCodeSnippet
+  otb::ogr::DataSource::Pointer input = otb::ogr::DataSource::New(
+    argv[1], otb::ogr::DataSource::Modes::read);
+  InputGeometriesType::Pointer in_set = InputGeometriesType::New(input);
+  // Software Guide : EndCodeSnippet
+
+  // Software Guide : BeginLatex
+  //
+  // We need the image only to retrieve its projection information,
+  // i.e. map projection or sensor model parameters. Hence, the image
+  // pixels won't be read, only the header information using the
+  // \code{UpdateOutputInformation()} method.
+  //
+  // Software Guide : EndLatex
+
+  // Software Guide : BeginCodeSnippet
+  typedef otb::Image<unsigned short int, 2> ImageType;
+  typedef otb::ImageFileReader<ImageType>   ImageReaderType;
+  ImageReaderType::Pointer imageReader = ImageReaderType::New();
+  imageReader->SetFileName(argv[2]);
+  imageReader->UpdateOutputInformation();
+  // Software Guide : EndCodeSnippet
+
+  // Software Guide : BeginLatex
+  //
+  // The \doxygen{otb}{GeometriesProjectionFilter} will do the work of
+  // converting the vector data coordinates. It is usually a good idea
+  // to use it when you design applications reading or saving vector
+  // data.
+  //
+  // Software Guide : EndLatex
+
+  // Software Guide : BeginCodeSnippet
+  typedef otb::GeometriesProjectionFilter GeometriesFilterType;
+  GeometriesFilterType::Pointer filter = GeometriesFilterType::New();
+  // Software Guide : EndCodeSnippet
+
+  // Software Guide : BeginLatex
+  //
+  // Information concerning the original projection of the vector data
+  // will be automatically retrieved from the metadata. Nothing else
+  // is needed from you:
+  //
+  // Software Guide : EndLatex
+
+  // Software Guide : BeginCodeSnippet
+  filter->SetInput(in_set);
+  // Software Guide : EndCodeSnippet
+
+  // Software Guide : BeginLatex
+  //
+  // Information about the target projection is retrieved directly from
+  // the image:
+  //
+  // Software Guide : EndLatex
+
+  // Software Guide : BeginCodeSnippet
+  filter->SetOutputKeywordList(imageReader->GetOutput()->GetImageKeywordlist()); // nec qd capteur
+  filter->OutputImageReference.SetOrigin(imageReader->GetOutput()->GetOrigin()); // nec qd capteur
+  filter->OutputImageReference.SetSpacing(imageReader->GetOutput()->GetSpacing()); // nec qd capteur
+  filter->SetOutputProjectionRef( imageReader->GetOutput()->GetProjectionRef()); // ~ wkt
+  // Software Guide : EndCodeSnippet
+
+  // Software Guide : BeginLatex
+  //
+  // Finally, the result is saved into a new vector file.
+  //
+  // Software Guide : EndLatex
+
+  // Software Guide : BeginCodeSnippet
+  otb::ogr::DataSource::Pointer output = otb::ogr::DataSource::New(
+    argv[3], otb::ogr::DataSource::Modes::write);
+  OutputGeometriesType::Pointer out_set = OutputGeometriesType::New(output);
+
+  filter->SetOutput(out_set);
+  filter->Update();
+  // Software Guide : EndCodeSnippet
+
+  // Software Guide : BeginLatex
+  //
+  // It is worth noting that none of this code is specific to the
+  // vector data format. Whether you pass a shapefile, or a KML file,
+  // the correct driver will be automatically instantiated.
+  //
+  // Software Guide : EndLatex
+
+  return EXIT_SUCCESS;
+
+}
diff --git a/Examples/Projections/otbProjectionsExamplesTests.cxx b/Examples/Projections/otbProjectionsExamplesTests.cxx
index 52de224b84605d29084c443f7dac918fda0377d4..9efea6a56135ad044e08315c9560cbed140b0d93 100644
--- a/Examples/Projections/otbProjectionsExamplesTests.cxx
+++ b/Examples/Projections/otbProjectionsExamplesTests.cxx
@@ -26,6 +26,7 @@ void RegisterTests()
   REGISTER_TEST(OrthoRectificationExampleTest);
   REGISTER_TEST(MapProjectionExampleTest);
   REGISTER_TEST(VectorDataProjectionExampleTest);
+  REGISTER_TEST(GeometriesProjectionTest);
   REGISTER_TEST(EstimateRPCSensorModelExample);
 }
 
@@ -41,6 +42,10 @@ void RegisterTests()
 #define main VectorDataProjectionExampleTest
 #include "VectorDataProjectionExample.cxx"
 
+#undef main
+#define main GeometriesProjectionTest
+#include "GeometriesProjection.cxx"
+
 #undef main
 #define main EstimateRPCSensorModelExample
 #include "EstimateRPCSensorModelExample.cxx"
diff --git a/Utilities/ITK/Code/Common/itkMetaDataObject.h b/Utilities/ITK/Code/Common/itkMetaDataObject.h
index 45b04a2a14fbb7c7318a34687b1a0b6982020d35..fe6744eb3262698e9a27ae3e150b77dba381d60c 100644
--- a/Utilities/ITK/Code/Common/itkMetaDataObject.h
+++ b/Utilities/ITK/Code/Common/itkMetaDataObject.h
@@ -12,8 +12,8 @@
   Portions of this code are covered under the VTK copyright.
   See VTKCopyright.txt or http://www.kitware.com/VTKCopyright.htm for details.
 
-     This software is distributed WITHOUT ANY WARRANTY; without even 
-     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+     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.
 
 =========================================================================*/
@@ -128,7 +128,7 @@ public:
   virtual void Print(std::ostream& os) const;
 private:
   //This is made private to force the use of the MetaDataObject<MetaDataObjectType>::New() operator!
-  //void * operator new(size_t nothing) {};//purposefully not implemented
+  //void * operator new(size_t nothing) {}; //purposefully not implemented
   /**
    * \author Hans J. Johnson
    * A variable to store this derived type.
@@ -176,9 +176,9 @@ inline bool ExposeMetaData(MetaDataDictionary &Dictionary, const std::string key
     {
     return false;
     }
-  
+
   MetaDataObjectBase::Pointer baseObjectSmartPointer = Dictionary[key];
-  
+
   if(strcmp(typeid(T).name(),baseObjectSmartPointer->GetMetaDataObjectTypeName()) != 0)
     {
     return false;