/*=========================================================================
*
*  Copyright NumFOCUS
*
*  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.txt
*
*  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 sitkTransformToDisplacementFieldFilter_h
#define sitkTransformToDisplacementFieldFilter_h

/*
 * WARNING: DO NOT EDIT THIS FILE!
 * THIS FILE IS AUTOMATICALLY GENERATED BY THE SIMPLEITK BUILD PROCESS.
 * Please look at sitkImageSourceTemplate.h.in to make changes.
 */

#include <memory>

#include "sitkBasicFilters.h"
#include "sitkImageFilter.h"

namespace itk::simple {

    /**\class TransformToDisplacementFieldFilter
\brief Generate a displacement field from a coordinate transform.

Output information (spacing, size and direction) for the output image should be set. This information has the normal defaults of unit spacing, zero origin and identity direction. Optionally, the output information can be obtained from a reference image. If the reference image is provided and UseReferenceImage is On, then the spacing, origin and direction of the reference image will be used.

Since this filter produces an image which is a different size than its input, it needs to override several of the methods defined in ProcessObject in order to properly manage the pipeline execution model. In particular, this filter overrides ProcessObject::GenerateOutputInformation() .

This filter is implemented as a multithreaded filter. It provides a ThreadedGenerateData() method for its implementation.

\author Marius Staring, Leiden University Medical Center, The Netherlands.


This class was taken from the Insight Journal paper: https://doi.org/10.54294/4ids6q
\sa itk::simple::TransformToDisplacementFieldFilter for the procedural interface
\sa itk::TransformToDisplacementFieldFilter for the Doxygen on the original ITK class.
     */
    class SITKBasicFilters_EXPORT TransformToDisplacementFieldFilter : public ImageFilter {
    public:
      using Self = TransformToDisplacementFieldFilter;

      /** Destructor */
      virtual ~TransformToDisplacementFieldFilter();

      /** Default Constructor that takes no arguments and initializes
       * default parameters */
      TransformToDisplacementFieldFilter();

      /** Define the pixels types supported by this filter */
      using PixelIDTypeList = RealVectorPixelIDTypeList;



\

      /**
       * \brief Set the output pixel type, only sitkVectorFloat32 and sitkVectorFloat64 are supported.
       */
      SITK_RETURN_SELF_TYPE_HEADER SetOutputPixelType ( PixelIDValueEnum OutputPixelType ) { this->m_OutputPixelType = OutputPixelType; return *this; }

      /**
       * \brief Get the ouput pixel type.
       */
      PixelIDValueEnum GetOutputPixelType() const { return this->m_OutputPixelType; }\

      /**
       * Set/Get the size of the output image.
       */
      SITK_RETURN_SELF_TYPE_HEADER SetSize ( std::vector<unsigned int> Size ) { this->m_Size = std::move(Size); return *this; }

      /**
       * Set/Get the size of the output image.
       */
      std::vector<unsigned int> GetSize() const { return this->m_Size; }\

      /**
       * Set the output image origin.
       */
      SITK_RETURN_SELF_TYPE_HEADER SetOutputOrigin ( std::vector<double> OutputOrigin ) { this->m_OutputOrigin = std::move(OutputOrigin); return *this; }

      /**
       * Get the output image origin.
       */
      std::vector<double> GetOutputOrigin() const { return this->m_OutputOrigin; }\

      /**
       * Set the output image spacing.
       */
      SITK_RETURN_SELF_TYPE_HEADER SetOutputSpacing ( std::vector<double> OutputSpacing ) { this->m_OutputSpacing = std::move(OutputSpacing); return *this; }

      /**
       * Get the output image spacing.
       */
      std::vector<double> GetOutputSpacing() const { return this->m_OutputSpacing; }\

      /**
       * Set the output direction cosine matrix.
       */
      SITK_RETURN_SELF_TYPE_HEADER SetOutputDirection ( std::vector<double> OutputDirection ) { this->m_OutputDirection = OutputDirection; return *this; }

      /**
       * Set the output direction cosine matrix.
       */
      std::vector<double> GetOutputDirection() const { return this->m_OutputDirection; }

      /** Name of this class */
      std::string GetName() const { return std::string ("TransformToDisplacementFieldFilter"); }

      /** Print ourselves out */
      std::string ToString() const;


      /** Execute the filter on the input image */

      Image Execute ( const Transform & transform );


      /** This methods sets the size, origin, spacing and direction to that of the provided image */
      void SetReferenceImage(const Image & refImage );


    private:

      /** Setup for member function dispatching */

      using MemberFunctionType = Image (Self::*)( const Transform * transform );
      template <class TImageType> Image ExecuteInternal ( const Transform * transform );


      friend struct detail::MemberFunctionAddressor<MemberFunctionType>;

      std::unique_ptr<detail::MemberFunctionFactory<MemberFunctionType> > m_MemberFactory;


      PixelIDValueEnum  m_OutputPixelType{itk::simple::sitkVectorFloat64};

      std::vector<unsigned int>  m_Size{std::vector<unsigned int>(3, 64)};

      std::vector<double>  m_OutputOrigin{std::vector<double>(3, 0.0)};

      std::vector<double>  m_OutputSpacing{std::vector<double>(3, 1.0)};

      /* Passing a zero sized array, defaults to identiy matrix. The size of the array must exactly match the direction matrix for the dimension of the image. */
      std::vector<double>  m_OutputDirection{std::vector<double>()};





    };



   /**
     * \brief Generate a displacement field from a coordinate transform.
     *
     * This function directly calls the execute method of TransformToDisplacementFieldFilter
     * in order to support a procedural API
     *
     * \sa itk::simple::TransformToDisplacementFieldFilter for the object oriented interface
     */
SITKBasicFilters_EXPORT Image TransformToDisplacementField ( const Transform & transform, PixelIDValueEnum outputPixelType = itk::simple::sitkVectorFloat64, std::vector<unsigned int> size = std::vector<unsigned int>(3, 64), std::vector<double> outputOrigin = std::vector<double>(3, 0.0), std::vector<double> outputSpacing = std::vector<double>(3, 1.0), std::vector<double> outputDirection = std::vector<double>() );
}
#endif
