/*=========================================================================
*
*  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 sitkThresholdSegmentationLevelSetImageFilter_h
#define sitkThresholdSegmentationLevelSetImageFilter_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 ThresholdSegmentationLevelSetImageFilter
\brief Segments structures in images based on intensity values.

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


\par OVERVIEW
This class is a level set method segmentation filter. It constructs a speed function which is close to zero at the upper and lower bounds of an intensity window, effectively locking the propagating front onto those edges. Elsewhere, the front will propagate quickly.


\par INPUTS
This filter requires two inputs. The first input is a seed image. This seed image must contain an isosurface that you want to use as the seed for your segmentation. It can be a binary, graylevel, or floating point image. The only requirement is that it contain a closed isosurface that you will identify as the seed by setting the IsosurfaceValue parameter of the filter. For a binary image you will want to set your isosurface value halfway between your on and off values (i.e. for 0's and 1's, use an isosurface value of 0.5).


\par 
The second input is the feature image. This is the image from which the speed function will be calculated. For most applications, this is the image that you want to segment. The desired isosurface in your seed image should lie within the region of your feature image that you are trying to segment. Note that this filter does no preprocessing of the feature image before thresholding.


\par 
See SegmentationLevelSetImageFilter for more information on Inputs.


\par OUTPUTS
The filter outputs a single, scalar, real-valued image. Positive values in the output image are inside the segmented region and negative values in the image are outside of the inside region. The zero crossings of the image correspond to the position of the level set front.


\par 
See SparseFieldLevelSetImageFilter and SegmentationLevelSetImageFilter for more information.


\par PARAMETERS
In addition to parameters described in SegmentationLevelSetImageFilter , this filter adds the UpperThreshold and LowerThreshold. See ThresholdSegmentationLevelSetFunction for a description of how these values affect the segmentation.


\see SegmentationLevelSetImageFilter 


\see ThresholdSegmentationLevelSetFunction , 


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

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

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

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

      /**
       */
      SITK_RETURN_SELF_TYPE_HEADER SetLowerThreshold ( double LowerThreshold ) { this->m_LowerThreshold = LowerThreshold; return *this; }

      /**
       */
      double GetLowerThreshold() const { return this->m_LowerThreshold; }\

      /**
       * Get/Set the threshold values that will be used to calculate the speed function.
       */
      SITK_RETURN_SELF_TYPE_HEADER SetUpperThreshold ( double UpperThreshold ) { this->m_UpperThreshold = UpperThreshold; return *this; }

      /**
       */
      double GetUpperThreshold() const { return this->m_UpperThreshold; }\

      /**
       */
      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 ("ThresholdSegmentationLevelSetImageFilter"); }

      /** 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;


      double  m_LowerThreshold{0.0};

      double  m_UpperThreshold{255.0};

      /* 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};


      uint32_t m_ElapsedIterations{0};

      double m_RMSChange{0.0};


      bool m_InPlace{false};
    };

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

     /** @} */
}
#endif
