diff --git a/Modules/Core/Functor/include/otbFunctorImageFilter.h b/Modules/Core/Functor/include/otbFunctorImageFilter.h index ddeb95167b3a85de92e4853edb2f7473d074f4fc..75a3fd1ab672d04f61ead3e7c71935d3db862430 100644 --- a/Modules/Core/Functor/include/otbFunctorImageFilter.h +++ b/Modules/Core/Functor/include/otbFunctorImageFilter.h @@ -21,7 +21,7 @@ #ifndef otbFunctorImageFilter_h #define otbFunctorImageFilter_h -#include "otbVariadicInputsImageFilter.h" +#include "otbVariadicNamedInputsImageFilter.h" #include "otbImage.h" #include "otbVectorImage.h" #include "itkDefaultConvertPixelTraits.h" @@ -122,29 +122,46 @@ template <class T> struct ImageTypeDeduction<const T &> * - InputHasNeighborhood a tuple of N false_type or true_type to denote * - if Ith arg of operator() expects a neighborhood. */ -template <typename T> struct FunctorFilterSuperclassHelper : public FunctorFilterSuperclassHelper<decltype(&T::operator())> {}; + + +template <typename T, typename TNameMap> struct FunctorFilterSuperclassHelper : public FunctorFilterSuperclassHelper<decltype(&T::operator()),TNameMap> {}; /// Partial specialisation for R(*)(T...) -template <typename R, typename... T> struct FunctorFilterSuperclassHelper<R(*)(T...)> +template <typename R, typename... T, typename TNameMap> struct FunctorFilterSuperclassHelper<R(*)(T...),TNameMap> { using OutputImageType = typename ImageTypeDeduction<R>::ImageType; - using FilterType = VariadicInputsImageFilter<OutputImageType,typename ImageTypeDeduction<typename PixelTypeDeduction<T>::PixelType>::ImageType...>; + template <typename V> using InputImageType = typename ImageTypeDeduction<typename PixelTypeDeduction<V>::PixelType>::ImageType; + + using FilterType = typename std::conditional<std::is_void<TNameMap>::value, + VariadicInputsImageFilter<OutputImageType,InputImageType<T>...>, + VariadicNamedInputsImageFilter<OutputImageType,TNameMap,InputImageType<T>...>>::type; + using InputHasNeighborhood = std::tuple<typename IsNeighborhood<T>::ValueType...>; }; // Partial specialisation for R(C::*)(T...) const -template <typename C, typename R, typename... T> struct FunctorFilterSuperclassHelper<R(C::*)(T...) const> +template <typename C, typename R, typename... T, typename TNameMap> struct FunctorFilterSuperclassHelper<R(C::*)(T...) const, TNameMap> { using OutputImageType = typename ImageTypeDeduction<R>::ImageType; - using FilterType = VariadicInputsImageFilter<OutputImageType,typename ImageTypeDeduction<typename PixelTypeDeduction<T>::PixelType>::ImageType...>; + template <typename V> using InputImageType = typename ImageTypeDeduction<typename PixelTypeDeduction<V>::PixelType>::ImageType; + + using FilterType = typename std::conditional<std::is_void<TNameMap>::value, + VariadicInputsImageFilter<OutputImageType,InputImageType<T>...>, + VariadicNamedInputsImageFilter<OutputImageType,TNameMap,InputImageType<T>...>>::type; + using InputHasNeighborhood = std::tuple<typename IsNeighborhood<T>::ValueType...>; }; // Partial specialisation for R(C::*)(T...) -template <typename C, typename R, typename... T> struct FunctorFilterSuperclassHelper<R(C::*)(T...)> +template <typename C, typename R, typename... T, typename TNameMap> struct FunctorFilterSuperclassHelper<R(C::*)(T...), TNameMap> { using OutputImageType = typename ImageTypeDeduction<R>::ImageType; - using FilterType = VariadicInputsImageFilter<OutputImageType,typename ImageTypeDeduction<typename PixelTypeDeduction<T>::PixelType>::ImageType...>; + template <typename V> using InputImageType = typename ImageTypeDeduction<typename PixelTypeDeduction<V>::PixelType>::ImageType; + + using FilterType = typename std::conditional<std::is_void<TNameMap>::value, + VariadicInputsImageFilter<OutputImageType,InputImageType<T>...>, + VariadicNamedInputsImageFilter<OutputImageType,TNameMap,InputImageType<T>...>>::type; + using InputHasNeighborhood = std::tuple<typename IsNeighborhood<T>::ValueType...>; }; @@ -173,7 +190,7 @@ template <typename C, typename R, typename... T> struct FunctorFilterSuperclassH * provided it returns a scalar type. If your lambda returns a * VariableLengthVector, see the other NewFunctorFilter implementation. */ -template <typename Functor> auto NewFunctorFilter(const Functor& f, itk::Size<2> radius = {{0,0}}); +template <typename Functor, typename TNameMap = void> auto NewFunctorFilter(const Functor& f, itk::Size<2> radius = {{0,0}}); /** \class FunctorImageFilter @@ -186,9 +203,9 @@ template <typename Functor> auto NewFunctorFilter(const Functor& f, itk::Size<2> * * \ingroup OTBFunctor */ -template <class TFunction> +template <class TFunction, class TNameMap = void> class ITK_EXPORT FunctorImageFilter - : public FunctorFilterSuperclassHelper<TFunction>::FilterType + : public FunctorFilterSuperclassHelper<TFunction, TNameMap>::FilterType { public: @@ -199,7 +216,8 @@ public: using ConstPointer = itk::SmartPointer<const Self>; // Superclass through the helper struct - using Superclass = typename FunctorFilterSuperclassHelper<TFunction>::FilterType; + using SuperclassHelper = FunctorFilterSuperclassHelper<TFunction,TNameMap>; + using Superclass = typename SuperclassHelper::FilterType; using OutputImageType = typename Superclass::OutputImageType; using OutputImageRegionType = typename OutputImageType::RegionType; @@ -207,7 +225,7 @@ public: // A tuple of bool of the same size as the number of arguments in // the functor - using InputHasNeighborhood = typename FunctorFilterSuperclassHelper<TFunction>::InputHasNeighborhood; + using InputHasNeighborhood = typename SuperclassHelper::InputHasNeighborhood; using InputTypesTupleType = typename Superclass::InputTypesTupleType; template<size_t I> using InputImageType = typename Superclass::template InputImageType<I>; using Superclass::NumberOfInputs; @@ -244,7 +262,7 @@ protected: private: /// Actual creation of the filter is handled by this free function - friend auto NewFunctorFilter<TFunction>(const TFunction& f, itk::Size<2> radius); + friend auto NewFunctorFilter<TFunction,TNameMap>(const TFunction& f, itk::Size<2> radius); /** Overload of ThreadedGenerateData */ void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId) override; @@ -268,9 +286,9 @@ private: }; // Actual implementation of NewFunctorFilter free function -template <typename Functor> auto NewFunctorFilter(const Functor& f, itk::Size<2> radius) +template <typename Functor, typename TNameMap> auto NewFunctorFilter(const Functor& f, itk::Size<2> radius) { - using FilterType = FunctorImageFilter<Functor>; + using FilterType = FunctorImageFilter<Functor,TNameMap>; using PointerType = typename FilterType::Pointer; PointerType p = new FilterType(f,radius); @@ -325,11 +343,11 @@ private: */ -template <typename Functor> auto NewFunctorFilter(const Functor& f, unsigned int numberOfOutputBands, itk::Size<2> radius) +template <typename Functor, typename TNameMap = void> auto NewFunctorFilter(const Functor& f, unsigned int numberOfOutputBands, itk::Size<2> radius) { using FunctorType = NumberOfOutputBandsDecorator<Functor>; FunctorType decoratedF(f,numberOfOutputBands); - return NewFunctorFilter(decoratedF,radius); + return NewFunctorFilter<FunctorType,TNameMap>(decoratedF,radius); } diff --git a/Modules/Core/Functor/include/otbFunctorImageFilter.hxx b/Modules/Core/Functor/include/otbFunctorImageFilter.hxx index 4d80e69c3057070ee44996c683fab0933554ab18..cc6573d3c77e701fdb1ee680412eac06c6cb5922 100644 --- a/Modules/Core/Functor/include/otbFunctorImageFilter.hxx +++ b/Modules/Core/Functor/include/otbFunctorImageFilter.hxx @@ -176,9 +176,9 @@ template <class F, class T, size_t N> struct NumberOfOutputComponents<F,otb::Vec } // end namespace functor_filter_details -template <class TFunction> +template <class TFunction, class TNameMap> void -FunctorImageFilter<TFunction> +FunctorImageFilter<TFunction, TNameMap> ::GenerateInputRequestedRegion() { // Get requested region for output @@ -191,9 +191,9 @@ FunctorImageFilter<TFunction> functor_filter_details::SetInputRequestedRegions(this->GetVInputs(),requestedRegion, m_Radius); } -template <class TFunction> +template <class TFunction, class TNameMap> void -FunctorImageFilter<TFunction>::GenerateOutputInformation() +FunctorImageFilter<TFunction, TNameMap>::GenerateOutputInformation() { // Call Superclass implementation Superclass::GenerateOutputInformation(); @@ -211,9 +211,9 @@ FunctorImageFilter<TFunction>::GenerateOutputInformation() /** * ThreadedGenerateData Performs the neighborhood-wise operation */ -template <class TFunction> +template <class TFunction, class TNameMap> void -FunctorImageFilter<TFunction> +FunctorImageFilter<TFunction, TNameMap> ::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId) { // Build output iterator diff --git a/Modules/Core/Functor/include/otbVariadicNamedInputsImageFilter.h b/Modules/Core/Functor/include/otbVariadicNamedInputsImageFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..a2c342ffc6129f54ca97a82f6c194fdcf8dcfa5b --- /dev/null +++ b/Modules/Core/Functor/include/otbVariadicNamedInputsImageFilter.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES) + * + * This file is part of Orfeo Toolbox + * + * https://www.orfeo-toolbox.org/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef otb_VariadicNamedInputsImageFilter_h +#define otb_VariadicNamedInputsImageFilter_h + +#include "otbVariadicInputsImageFilter.h" + +namespace otb { + +/// TODO: Documentation + +namespace internal +{ +template<typename Arg, typename Tuple> struct tuple_index; +template<typename Arg, typename...Args> struct tuple_index<Arg, std::tuple<Arg,Args...> > +{ + static constexpr std::size_t value = 0; +}; + +template<typename Arg, typename NotMatching, typename...Args> struct tuple_index<Arg, std::tuple<NotMatching,Args...>> +{ + static_assert(sizeof...(Args)>0,"Could not find requested type in tuple"); + static constexpr std::size_t value = 1 + tuple_index<Arg,std::tuple<Args...>>::value; +}; +} + +template<class TOuptut, class TInputNameMap, class ... TInputs> class VariadicNamedInputsImageFilter : public VariadicInputsImageFilter<TOuptut,TInputs...> +{ +public: + using Self = VariadicNamedInputsImageFilter<TOuptut,TInputNameMap, TInputs...>; + using Pointer = itk::SmartPointer<Self>; + using ConstPointer = itk::SmartPointer<const Self>; + using Superclass = VariadicInputsImageFilter<TOuptut, TInputs...>;; + + using InputTypesTupleType = typename Superclass::InputTypesTupleType; + template <size_t I> using InputImageType = typename Superclass::template InputImageType<I>; + static constexpr size_t NumberOfInputs = Superclass::NumberOfInputs; + + static_assert(std::tuple_size<TInputNameMap>::value == NumberOfInputs,"Tuple for input name does not match the size of ... TInputs"); + + itkNewMacro(Self); + + template <typename Tag> void SetVNamedInput(const InputImageType<internal::tuple_index<Tag, TInputNameMap>::value> * inputPtr) + { + constexpr size_t idx = internal::tuple_index<Tag, TInputNameMap>::value; + this->SetNthInput(idx,const_cast<InputImageType<idx> *>(inputPtr)); + } + + template <typename Tag> const InputImageType<internal::tuple_index<Tag,TInputNameMap>::value> * GetVNamedInput() + { + constexpr size_t idx = internal::tuple_index<Tag, TInputNameMap>::value; + return dynamic_cast<const InputImageType<idx> *>(this->GetInput(idx)); + } + +protected: + VariadicNamedInputsImageFilter() = default; + ~VariadicNamedInputsImageFilter() = default; + +private: + VariadicNamedInputsImageFilter(const Self&) = delete; + void operator=(const Self&) = delete; +}; + +} + +#endif diff --git a/Modules/Core/Functor/test/otbFunctorImageFilter.cxx b/Modules/Core/Functor/test/otbFunctorImageFilter.cxx index e1cd5360e2713ed13d4f5c5761a7b4b58c7ed871..df88b7a10821e9a8cf61585575c4274af79636f0 100644 --- a/Modules/Core/Functor/test/otbFunctorImageFilter.cxx +++ b/Modules/Core/Functor/test/otbFunctorImageFilter.cxx @@ -25,6 +25,7 @@ #include "itkNeighborhood.h" #include "otbVariadicAddFunctor.h" #include "otbVariadicConcatenateFunctor.h" +#include "otbVariadicNamedInputsImageFilter.h" #include <tuple> #include <numeric> @@ -99,7 +100,7 @@ template <typename T> struct TypesCheck // Build and run filter auto functor = TestOperator<TOut,TIn>{}; auto filter = NewFunctorFilter(functor); - + using FilterType = typename decltype(filter)::ObjectType; static_assert(FilterType::NumberOfInputs == 1,""); static_assert(std::is_same<typename FilterType::template InputImageType<0>, InputImageType>::value, ""); @@ -108,6 +109,13 @@ template <typename T> struct TypesCheck filter->SetInput1(in); filter->template SetVInput<0>(in); // template keyword to avoid C++ parse ambiguity filter->Update(); + + // Test named input version + struct tag{}; + using inputNames = std::tuple<tag>; + auto filter1 = NewFunctorFilter<decltype(functor),inputNames>(functor); + filter1->template SetVNamedInput<tag>(in); + filter1->Update(); } TypesCheck() @@ -274,6 +282,17 @@ int otbFunctorImageFilter(int itkNotUsed(argc), char * itkNotUsed(argv) []) filter->SetVInputs(vimage,image); std::cout<<filter->GetVInput<0>()<< filter->GetVInput<1>()<<std::endl; + // Test VariadicNamedInputsImageFilter + struct xs {}; + struct pan {}; + using Names = std::tuple<xs,pan>; + auto filterWithNames = otb::VariadicNamedInputsImageFilter<VectorImageType, Names, VectorImageType,ImageType>::New(); + filterWithNames->SetVNamedInput<xs>(vimage); + filterWithNames->SetVNamedInput<pan>(image); + + std::cout<<filterWithNames->GetVNamedInput<xs>()<< filterWithNames->GetVNamedInput<pan>()<<std::endl; + + // test FunctorImageFilter with a lambda double scale = 10.; @@ -314,6 +333,8 @@ int otbFunctorImageFilter(int itkNotUsed(argc), char * itkNotUsed(argv) []) // Test FunctorImageFilter With VariadicAdd functor using AddFunctorType = Functor::VariadicAdd<double, double, double>; auto add = NewFunctorFilter(AddFunctorType{}); + add->SetVInput<0>(image); + add->SetVInput<1>(image); add->SetVInputs(image,image); add->Update(); @@ -346,7 +367,7 @@ int otbFunctorImageFilter(int itkNotUsed(argc), char * itkNotUsed(argv) []) auto argFilter = NewFunctorFilter(LambdaComplex); argFilter->SetVInputs(cimage); argFilter->Update(); - + return EXIT_SUCCESS; }