/*=========================================================================
*
*  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 sitkShapeDetectionLevelSetImageFilter_h
#define sitkShapeDetectionLevelSetImageFilter_h

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

#include <memory>

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

namespace itk::simple {

    /**\class ShapeDetectionLevelSetImageFilter
\brief Segments structures in images based on a user supplied edge potential map.

\par IMPORTANT
The SegmentationLevelSetImageFilter class and the ShapeDetectionLevelSetFunction class contain additional information necessary to gain full understanding of how to use this filter.


\par OVERVIEW
This class is a level set method segmentation filter. An initial contour is propagated outwards (or inwards) until it ''sticks'' to the shape boundaries. This is done by using a level set speed function based on a user supplied edge potential map. This approach for segmentation follows that of Malladi et al (1995).


\par INPUTS
This filter requires two inputs. The first input is a initial level set. The initial level set is a real image which contains the initial contour/surface as the zero level set. For example, a signed distance function from the initial contour/surface is typically used. Note that for this algorithm the initial contour has to be wholly within (or wholly outside) the structure to be segmented.


\par 
The second input is the feature image. For this filter, this is the edge potential map. General characteristics of an edge potential map is that it has values close to zero in regions near the edges and values close to one inside the shape itself. Typically, the edge potential map is compute from the image gradient, for example:


 \f[ g(I) = 1 / ( 1 + | (\nabla * G)(I)| ) \f] \f[ g(I) = \exp^{-|(\nabla * G)(I)|} \f] 

where \f$ I \f$ is image intensity and \f$ (\nabla * G) \f$ is the derivative of Gaussian operator.

\par 
See SegmentationLevelSetImageFilter and SparseFieldLevelSetImageFilter for more information on Inputs.


\par PARAMETERS
The PropagationScaling parameter can be used to switch from propagation outwards (POSITIVE scaling parameter) versus propagating inwards (NEGATIVE scaling parameter).


The smoothness of the resulting contour/surface can be adjusted using a combination of PropagationScaling and CurvatureScaling parameters. The larger the CurvatureScaling parameter, the smoother the resulting contour. The CurvatureScaling parameter should be non-negative for proper operation of this algorithm. To follow the implementation in Malladi et al paper, set the PropagationScaling to \f$\pm 1.0\f$ and CurvatureScaling to \f$ \epsilon \f$ .

Note that there is no advection term for this filter. Setting the advection scaling will have no effect.

\par OUTPUTS
The filter outputs a single, scalar, real-valued image. Negative values in the output image represent the inside of the segmented region and positive values in the image represent the outside of the segmented region. The zero crossings of the image correspond to the position of the propagating front.


\par 
See SparseFieldLevelSetImageFilter and SegmentationLevelSetImageFilter for more information.


\par REFERENCES



\par 
"Shape Modeling with Front Propagation: A Level Set Approach", R. Malladi, J. A. Sethian and B. C. Vermuri. IEEE Trans. on Pattern Analysis and Machine Intelligence, Vol 17, No. 2, pp 158-174, February 1995


\see SegmentationLevelSetImageFilter 


\see ShapeDetectionLevelSetFunction 


\see SparseFieldLevelSetImageFilter
\sa itk::simple::ShapeDetectionLevelSet for the procedural interface
\sa itk::ShapeDetectionLevelSetImageFilter for the Doxygen on the original ITK class.
     */
    class SITKBasicFilters_EXPORT ShapeDetectionLevelSetImageFilter : public ImageFilter {
    public:
      using Self = ShapeDetectionLevelSetImageFilter;

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

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

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

      /**
       */
      SITK_RETURN_SELF_TYPE_HEADER SetMaximumRMSError ( double MaximumRMSError ) { this->m_MaximumRMSError = MaximumRMSError; return *this; }

      /**
       */
      double GetMaximumRMSError() const { return this->m_MaximumRMSError; }\

      /**
       */
      SITK_RETURN_SELF_TYPE_HEADER SetPropagationScaling ( double PropagationScaling ) { this->m_PropagationScaling = PropagationScaling; return *this; }

      /**
       */
      double GetPropagationScaling() const { return this->m_PropagationScaling; }\

      /**
       */
      SITK_RETURN_SELF_TYPE_HEADER SetCurvatureScaling ( double CurvatureScaling ) { this->m_CurvatureScaling = CurvatureScaling; return *this; }

      /**
       */
      double GetCurvatureScaling() const { return this->m_CurvatureScaling; }\

      /**
       */
      SITK_RETURN_SELF_TYPE_HEADER SetNumberOfIterations ( uint32_t NumberOfIterations ) { this->m_NumberOfIterations = NumberOfIterations; return *this; }

      /**
       */
      uint32_t GetNumberOfIterations() const { return this->m_NumberOfIterations; }\

      /**
       */
      SITK_RETURN_SELF_TYPE_HEADER SetReverseExpansionDirection ( bool ReverseExpansionDirection ) { this->m_ReverseExpansionDirection = ReverseExpansionDirection; return *this; }

      /** Set the value of ReverseExpansionDirection to true or false respectfully. */
      SITK_RETURN_SELF_TYPE_HEADER ReverseExpansionDirectionOn() { return this->SetReverseExpansionDirection(true); }
      SITK_RETURN_SELF_TYPE_HEADER ReverseExpansionDirectionOff() { return this->SetReverseExpansionDirection(false); }

      /**
       */
      bool GetReverseExpansionDirection() const { return this->m_ReverseExpansionDirection; }
     /** \brief Number of iterations run.
      *
      *
      * This is a measurement. Its value is updated in the Execute
      * methods, so the value will only be valid after an execution.
      */
     uint32_t GetElapsedIterations() const { return this->m_ElapsedIterations; };

     /** \brief The Root Mean Square of the levelset upon termination.
      *
      *
      * This is a measurement. Its value is updated in the Execute
      * methods, so the value will only be valid after an execution.
      */
     double GetRMSChange() const { return this->m_RMSChange; };


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

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


      /** Execute the filter on the input image */
#ifndef SWIG
      Image Execute ( Image && initialImage, const Image & featureImage );
#endif
      Image Execute ( const Image & initialImage, const Image & featureImage );

    private:

      /** Setup for member function dispatching */

      using MemberFunctionType = Image (Self::*)( const Image * initialImage, const Image * featureImage );
      template <class TImageType> Image ExecuteInternal ( const Image * initialImage, const Image * featureImage );


      friend struct detail::MemberFunctionAddressor<MemberFunctionType>;

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


      /* Value of RMS change below which the filter should stop. This is a convergence criterion. */
      double  m_MaximumRMSError{0.02};

      /* Weight of direct propagation contribution to the speed term */
      double  m_PropagationScaling{1.0};

      /* Weight of the curvature contribution to the speed term */
      double  m_CurvatureScaling{1.0};

      /* Number of iterations to run */
      uint32_t  m_NumberOfIterations{1000u};

      /* Turn On/Off the flag which determines whether Positive or Negative speed terms will cause surface expansion.  If set to TRUE then negative speed terms will cause the surface to expand and positive speed terms will cause the surface to contract.  If set to FALSE (default) then positive speed terms will cause the surface to expand and negative speed terms will cause the surface to contract.  This method can be safely used to reverse the expansion/contraction as appropriate to a particular application or data set. */
      bool  m_ReverseExpansionDirection{false};

      /* Level Set filter that uses propagation and curvature terms. */
      uint32_t m_ElapsedIterations{0};
      /* Level Set filter that uses propagation and curvature terms. */
      double m_RMSChange{0.0};


      bool m_InPlace{false};
    };

    /**\
     * \brief Segments structures in images based on a user supplied edge potential map.
     *
     * This function directly calls the execute method of ShapeDetectionLevelSetImageFilter
     * in order to support a procedural API
     *
     * \sa itk::simple::ShapeDetectionLevelSetImageFilter for the object oriented interface
     * @{
     */
#ifndef SWIG
     SITKBasicFilters_EXPORT Image ShapeDetectionLevelSet ( Image && initialImage, const Image & featureImage, double maximumRMSError = 0.02, double propagationScaling = 1.0, double curvatureScaling = 1.0, uint32_t numberOfIterations = 1000u, bool reverseExpansionDirection = false );
#endif
     SITKBasicFilters_EXPORT Image ShapeDetectionLevelSet ( const Image & initialImage, const Image & featureImage, double maximumRMSError = 0.02, double propagationScaling = 1.0, double curvatureScaling = 1.0, uint32_t numberOfIterations = 1000u, bool reverseExpansionDirection = false );

     /** @} */
}
#endif
