diff --git a/Code/Projections/otbGeometriesProjectionFilter.cxx b/Code/Projections/otbGeometriesProjectionFilter.cxx index ffb86c6bb189e6037f0ad2b5f27fe768cd2b0241..d3297b54f812571c61ecbd41c9990b5147e7223f 100644 --- a/Code/Projections/otbGeometriesProjectionFilter.cxx +++ b/Code/Projections/otbGeometriesProjectionFilter.cxx @@ -278,3 +278,11 @@ void otb::GeometriesProjectionFilter::DoProcessLayer(ogr::Layer const& source, o m_TransformationFunctor(destination); // if TransformedElementType == layer } } + +/*virtual*/ +void otb::GeometriesProjectionFilter::DoDefineNewLayerFields(ogr::Layer const& source, ogr::Layer & dest) const + +{ + std::cout << "otb::GeometriesProjectionFilter::DoDefineNewLayerFields\n"; + m_TransformationFunctor.DefineFields(source, dest); +} diff --git a/Code/Projections/otbGeometriesProjectionFilter.h b/Code/Projections/otbGeometriesProjectionFilter.h index e5ccfb5723c068a5451bcafb7390ca86086ebdef..f77fb231320ab5e9c6a347a288a5f023341bdf06 100644 --- a/Code/Projections/otbGeometriesProjectionFilter.h +++ b/Code/Projections/otbGeometriesProjectionFilter.h @@ -117,6 +117,7 @@ private: virtual OGRSpatialReference* DoDefineNewLayerSpatialReference(ogr::Layer const& source) const; virtual void DoProcessLayer(ogr::Layer const& source, ogr::Layer & destination) const; virtual void DoFinalizeInitialisation(); + virtual void DoDefineNewLayerFields(ogr::Layer const& source, ogr::Layer & dest) const; protected: /** Default constructor. */ @@ -160,7 +161,7 @@ private: //@{ typedef ReprojectTransformationFunctor TransformationFunctorType; typedef TransformationFunctorType::TransformedElementType TransformedElementType; - typedef TransformationFunctorDispatcher<TransformationFunctorType, TransformedElementType> + typedef TransformationFunctorDispatcher<TransformationFunctorType, TransformedElementType, FieldCopyTransformation> TransformationFunctorDispatcherType; TransformationFunctorDispatcherType m_TransformationFunctor; diff --git a/Code/UtilitiesAdapters/OGRAdapters/otbGeometriesToGeometriesFilter.cxx b/Code/UtilitiesAdapters/OGRAdapters/otbGeometriesToGeometriesFilter.cxx index d8319220d71067882324d2bad5501da4dcd19642..a8af687f2325e2fe9c902fe6a03fb8d9d54277d5 100644 --- a/Code/UtilitiesAdapters/OGRAdapters/otbGeometriesToGeometriesFilter.cxx +++ b/Code/UtilitiesAdapters/OGRAdapters/otbGeometriesToGeometriesFilter.cxx @@ -61,6 +61,7 @@ struct ProcessVisitor : boost::static_visitor<> m_filter.DoDefineNewLayerGeometryType(sourceLayer), otb::ogr::StringListConverter(m_filter.DoDefineNewLayerOptions(sourceLayer)).to_ogr() ); + m_filter.DoDefineNewLayerFields(sourceLayer, destLayer); m_filter.DoProcessLayer(sourceLayer, destLayer); } } diff --git a/Code/UtilitiesAdapters/OGRAdapters/otbGeometriesToGeometriesFilter.h b/Code/UtilitiesAdapters/OGRAdapters/otbGeometriesToGeometriesFilter.h index 4e8d2d9dac18b2162790d4e7eab34b9e756aa6bf..14c1e43072b29db9a52587ee1fdcc1181dbaddd5 100644 --- a/Code/UtilitiesAdapters/OGRAdapters/otbGeometriesToGeometriesFilter.h +++ b/Code/UtilitiesAdapters/OGRAdapters/otbGeometriesToGeometriesFilter.h @@ -120,6 +120,8 @@ private: */ virtual std::vector<std::string> DoDefineNewLayerOptions(ogr::Layer const& source) const; + virtual void DoDefineNewLayerFields(ogr::Layer const& source, ogr::Layer & dest) const = 0; + /** Hook used to conclude the initialization phase. * As ITK doesn't follow a <em>the constructor set the object in a final, and * ready to be used, state</em>, this step is required to do that once all @@ -132,6 +134,38 @@ private: friend struct ::ProcessVisitor; }; +struct FieldCopyTransformation + { + OGRFeatureDefn & getDefinition(ogr::Layer & outLayer) const + { + return outLayer.GetLayerDefn(); + } + void fieldsTransform(ogr::Feature const& inoutFeature) const + { + // default => do nothing for in-place transformation + } + void fieldsTransform(ogr::Feature const& inFeature, ogr::Feature & outFeature) const + { + // default => copy all fields for copy transformation + assert(inFeature.GetSize() == outFeature.GetSize()); + for (size_t i=0,N=inFeature.GetSize(); i!=N; ++i) + { + outFeature[i].Assign(inFeature[i]); + } + } + + void DefineFields(ogr::Layer const& source, ogr::Layer & dest) const + { + std::cout << " FieldCopyTransformation::DefineFields()\n"; + OGRFeatureDefn & inDefinition = source.GetLayerDefn(); + for (int i=0,N=inDefinition.GetFieldCount(); i!=N; ++i) + { + std::cout << " - " << ogr::FieldDefn(*inDefinition.GetFieldDefn(i)) << "\n"; + dest.CreateField(*inDefinition.GetFieldDefn(i)); + } + } + }; + /**\ingroup GeometriesFilters * \class TransformationFunctorDispatcher @@ -147,7 +181,7 @@ private: * \since OTB v 3.14.0 * \todo Add a specialization for \c ogr::Feature. */ -template <class TransformationFunctor, class TransformedElementType> +template <class TransformationFunctor, class TransformedElementType, class FieldTransformationPolicy = FieldCopyTransformation> struct TransformationFunctorDispatcher { }; @@ -157,8 +191,9 @@ struct TransformationFunctorDispatcher * \tparam TransformationFunctor actual transformation functor * \since OTB v 3.14.0 */ -template <class TransformationFunctor> -struct TransformationFunctorDispatcher<TransformationFunctor, ogr::Layer> +template <class TransformationFunctor, class FieldTransformationPolicy> +struct TransformationFunctorDispatcher<TransformationFunctor, ogr::Layer, FieldTransformationPolicy> +: FieldTransformationPolicy { typedef typename TransformationFunctor::TransformedElementType TransformedElementType; BOOST_MPL_ASSERT((boost::is_same<ogr::Layer, TransformedElementType>)); @@ -171,35 +206,14 @@ private: TransformationFunctor m_functor; }; -template <class TransformationFunctor> -struct FieldTransformationPolicy - { - OGRFeatureDefn & getDefinition(ogr::Layer & outLayer) const - { - return outLayer.GetLayerDefn(); - } - void fieldsTransform(ogr::Feature const& inoutFeature) - { - // default => do nothing for in-place transformation - } - void fieldsTransform(ogr::Feature const& inFeature, ogr::Feature & outFeature) - { - // default => copy all fields for copy transformation - assert(inFeature.GetSize() == outFeature.GetSize()); - for (size_t i=0,N=inFeature.GetSize(); i!=N; ++i) - { - outFeature[i] = inFeature[i]; - } - } - }; - /**\ingroup GeometriesFilters * Specialization for \c OGRGeometry. * \tparam TransformationFunctor actual transformation functor * \since OTB v 3.14.0 */ -template <class TransformationFunctor> -struct TransformationFunctorDispatcher<TransformationFunctor, OGRGeometry> +template <class TransformationFunctor, class FieldTransformationPolicy> +struct TransformationFunctorDispatcher<TransformationFunctor, OGRGeometry, FieldTransformationPolicy> +: FieldTransformationPolicy { typedef typename TransformationFunctor::TransformedElementType TransformedElementType; BOOST_MPL_ASSERT((boost::is_same<OGRGeometry, TransformedElementType>)); @@ -220,10 +234,10 @@ private: * \since OTB v 3.14.0 * \todo Find a better name */ -template <class TransformationFunctor> +template <class TransformationFunctor, class FieldTransformationPolicy = FieldCopyTransformation> class ITK_EXPORT DefaultGeometriesToGeometriesFilter : public GeometriesToGeometriesFilter -, public TransformationFunctorDispatcher<TransformationFunctor, typename TransformationFunctor::TransformedElementType> +, public TransformationFunctorDispatcher<TransformationFunctor, typename TransformationFunctor::TransformedElementType, FieldTransformationPolicy> { public: /**\name Standard ITK typedefs */ @@ -237,7 +251,7 @@ public: //@{ typedef TransformationFunctor TransformationFunctorType; typedef typename TransformationFunctor::TransformedElementType TransformedElementType; - typedef TransformationFunctorDispatcher<TransformationFunctorType, TransformedElementType> + typedef TransformationFunctorDispatcher<TransformationFunctorType, TransformedElementType, FieldTransformationPolicy> TransformationFunctorDispatcherType; //@} @@ -257,6 +271,10 @@ protected: virtual ~DefaultGeometriesToGeometriesFilter(); virtual void DoProcessLayer(ogr::Layer const& source, ogr::Layer & destination) const; + virtual void DoDefineNewLayerFields(ogr::Layer const& source, ogr::Layer & dest) const + { + this->DefineFields(source, dest); + } private: // TransformationFunctorDispatcherType m_TransformationFunctor; }; diff --git a/Code/UtilitiesAdapters/OGRAdapters/otbGeometriesToGeometriesFilter.txx b/Code/UtilitiesAdapters/OGRAdapters/otbGeometriesToGeometriesFilter.txx index 91653bd1f7eb6d0aafb8bc0d0f79e8fcac7655dc..dddc59bfdc995f97654d2f47360c46df1a574d26 100644 --- a/Code/UtilitiesAdapters/OGRAdapters/otbGeometriesToGeometriesFilter.txx +++ b/Code/UtilitiesAdapters/OGRAdapters/otbGeometriesToGeometriesFilter.txx @@ -23,21 +23,21 @@ /*===========================================================================*/ /*==================[ DefaultGeometriesToGeometriesFilter ]==================*/ /*===========================================================================*/ -template <class TransformationFunctor> +template <class TransformationFunctor, class FieldTransformationPolicy> inline -otb::DefaultGeometriesToGeometriesFilter<TransformationFunctor>::DefaultGeometriesToGeometriesFilter() +otb::DefaultGeometriesToGeometriesFilter<TransformationFunctor, FieldTransformationPolicy>::DefaultGeometriesToGeometriesFilter() {} -template <class TransformationFunctor> +template <class TransformationFunctor, class FieldTransformationPolicy> inline /*virtual*/ -otb::DefaultGeometriesToGeometriesFilter<TransformationFunctor>::~DefaultGeometriesToGeometriesFilter() +otb::DefaultGeometriesToGeometriesFilter<TransformationFunctor, FieldTransformationPolicy>::~DefaultGeometriesToGeometriesFilter() {} -template <class TransformationFunctor> +template <class TransformationFunctor, class FieldTransformationPolicy> inline /*virtual*/ -void otb::DefaultGeometriesToGeometriesFilter<TransformationFunctor>::DoProcessLayer( +void otb::DefaultGeometriesToGeometriesFilter<TransformationFunctor, FieldTransformationPolicy>::DoProcessLayer( otb::ogr::Layer const& source, otb::ogr::Layer & destination) const { if (source != destination) @@ -56,17 +56,17 @@ void otb::DefaultGeometriesToGeometriesFilter<TransformationFunctor>::DoProcessL /*================[ TransformationFunctorDispatcher<layer> ]=================*/ /*===========================================================================*/ -template <class TransformationFunctor> +template <class TransformationFunctor, class FieldTransformationPolicy> inline -void otb::TransformationFunctorDispatcher<TransformationFunctor,otb::ogr::Layer>::operator()( +void otb::TransformationFunctorDispatcher<TransformationFunctor,otb::ogr::Layer,FieldTransformationPolicy>::operator()( otb::ogr::Layer const& in, otb::ogr::Layer & out) const { m_functor(in, out); } -template <class TransformationFunctor> +template <class TransformationFunctor, class FieldTransformationPolicy> inline -void otb::TransformationFunctorDispatcher<TransformationFunctor,otb::ogr::Layer>::operator()( +void otb::TransformationFunctorDispatcher<TransformationFunctor,otb::ogr::Layer,FieldTransformationPolicy>::operator()( otb::ogr::Layer & inout) const { @@ -76,26 +76,26 @@ void otb::TransformationFunctorDispatcher<TransformationFunctor,otb::ogr::Layer> /*===========================================================================*/ /*=============[ TransformationFunctorDispatcher<OGRGeometry> ]==============*/ /*===========================================================================*/ -template <class TransformationFunctor> +template <class TransformationFunctor, class FieldTransformationPolicy> inline -void otb::TransformationFunctorDispatcher<TransformationFunctor,OGRGeometry>::operator()( +void otb::TransformationFunctorDispatcher<TransformationFunctor,OGRGeometry,FieldTransformationPolicy>::operator()( otb::ogr::Layer const& in, otb::ogr::Layer & out) const { OGRFeatureDefn & defn = out.GetLayerDefn(); for (ogr::Layer::const_iterator b = in.begin(), e = in.end(); b != e; ++b) { ogr::Feature const feat = *b; - // TODO: field transformations... ogr::UniqueGeometryPtr g = m_functor(feat.GetGeometry()); ogr::Feature dest(defn); dest.SetGeometryDirectly(otb::move(g)); + this->fieldsTransform(feat, dest); out.CreateFeature(dest); } } -template <class TransformationFunctor> +template <class TransformationFunctor, class FieldTransformationPolicy> inline -void otb::TransformationFunctorDispatcher<TransformationFunctor,OGRGeometry>::operator()( +void otb::TransformationFunctorDispatcher<TransformationFunctor,OGRGeometry,FieldTransformationPolicy>::operator()( otb::ogr::Layer & inout) const { OGRFeatureDefn & defn = inout.GetLayerDefn(); @@ -105,7 +105,7 @@ void otb::TransformationFunctorDispatcher<TransformationFunctor,OGRGeometry>::op for (int i=0, N=inout.GetFeatureCount(true); i!=N; ++i) { ogr::Feature feat = *inout.start_at(i); - // TODO: field transformations... + this->fieldsTransform(feat); ogr::UniqueGeometryPtr g = m_functor(feat.GetGeometry()); feat.SetGeometryDirectly(otb::move(g)); inout.SetFeature(feat); diff --git a/Code/UtilitiesAdapters/OGRAdapters/otbOGRFieldWrapper.h b/Code/UtilitiesAdapters/OGRAdapters/otbOGRFieldWrapper.h index 8bcea0628765db9861cf7fd9c49772780243729a..d3f686c72b45f37246a4dbc48c49f6617eebca45 100644 --- a/Code/UtilitiesAdapters/OGRAdapters/otbOGRFieldWrapper.h +++ b/Code/UtilitiesAdapters/OGRAdapters/otbOGRFieldWrapper.h @@ -99,7 +99,8 @@ public: */ Field(Feature & feature, size_t index); /// %Field definition accessor. - FieldDefn const& GetDefinition() const; + FieldDefn const& GetDefinition() const + { return m_Definition; } /// %Field type accessor. OGRFieldType GetType() const { return m_Definition.GetType(); } diff --git a/Code/UtilitiesAdapters/OGRAdapters/otbOGRFieldWrapper.txx b/Code/UtilitiesAdapters/OGRAdapters/otbOGRFieldWrapper.txx index c821b416668253850bb9858bf1611a30edf31555..b213f5b7f359f4f11387f48f8899cf20890cdf1d 100644 --- a/Code/UtilitiesAdapters/OGRAdapters/otbOGRFieldWrapper.txx +++ b/Code/UtilitiesAdapters/OGRAdapters/otbOGRFieldWrapper.txx @@ -435,7 +435,11 @@ void otb::ogr::Field::Assign(Field const& f) { CheckInvariants(); f.CheckInvariants(); - assert(f.GetDefinition() == this->GetDefinition() && "Cannot assign from a field that doesn't have the same definition"); + assert(f.GetType() == this->GetType() && "Cannot assign from a field that doesn't have the same definition"); + // We can't assume the following as sometimes field names are altered by the + // datasource driver; for instance, shp driver truncates field names to 8 + // characters. + // assert(f.GetDefinition() == this->GetDefinition() && "Cannot assign from a field that doesn't have the same definition"); UncheckedAssign(f); CheckInvariants(); }