/*========================================================================= * * 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 * * https://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 itkLevelSetBase_h #define itkLevelSetBase_h #include #include "itkIntTypes.h" #include "itkCovariantVector.h" #include "itkMatrix.h" #include "itkNumericTraits.h" #include "itkDataObject.h" namespace itk { /** * \class LevelSetBase * \brief Abstract base class for the representation of a level-set function * * \tparam TInput Input type where the level set function will be evaluated * \tparam VDimension Dimension of the input space * \tparam TOutput Returned type when evaluating the level set function * \tparam TDomain Support of the level-set function (e.g. Image or QuadEdgeMesh) * \ingroup ITKLevelSetsv4 */ template class ITK_TEMPLATE_EXPORT LevelSetBase : public DataObject { public: ITK_DISALLOW_COPY_AND_MOVE(LevelSetBase); using Self = LevelSetBase; using Superclass = DataObject; using Pointer = SmartPointer; using ConstPointer = SmartPointer; /** \see LightObject::GetNameOfClass() */ itkOverrideGetNameOfClassMacro(LevelSetBase); static constexpr unsigned int Dimension = VDimension; using InputType = TInput; using OutputType = TOutput; using DomainType = TDomain; using OutputRealType = typename NumericTraits::RealType; using GradientType = CovariantVector; using HessianType = Matrix; /** Type used to define Regions */ using RegionType = IdentifierType; /** Returns the value of the level set function at a given location iP */ virtual OutputType Evaluate(const InputType & iP) const = 0; /** Returns the gradient of the level set function at a given location iP */ virtual GradientType EvaluateGradient(const InputType & iP) const = 0; /** Returns the hessian of the level set function at a given location iP */ virtual HessianType EvaluateHessian(const InputType & iP) const = 0; virtual OutputRealType EvaluateLaplacian(const InputType & iP) const = 0; virtual OutputRealType EvaluateGradientNorm(const InputType & iP) const; virtual OutputRealType EvaluateMeanCurvature(const InputType & iP) const = 0; /** * \class DataType * \brief Internal class used for one computed characteristic * * It holds the name of the characteristics, its value, and a boolean * to keep track if it has already been computed or not. * \ingroup ITKLevelSetsv4 */ template class ITK_TEMPLATE_EXPORT DataType { public: DataType() = delete; DataType(std::string iName) : m_Name(std::move(iName)) , m_Computed(false) {} DataType(const DataType & iData) : m_Name(iData.m_Name) , m_Value(iData.m_Value) , m_Computed(iData.m_Computed) {} ~DataType() = default; std::string m_Name; T m_Value; bool m_Computed; void operator=(const DataType & iData) { this->m_Name = iData.m_Name; this->m_Value = iData.m_Value; this->m_Computed = iData.m_Computed; } }; /** \struct LevelSetDataType * \brief Convenient data structure to cache computed characteristics * \ingroup ITKLevelSetsv4 */ struct LevelSetDataType { LevelSetDataType() : Value("Value") , Gradient("Gradient") , Hessian("Hessian") , Laplacian("Laplacian") , GradientNorm("GradientNorm") , MeanCurvature("MeanCurvature") , ForwardGradient("ForwardGradient") , BackwardGradient("BackwardGradient") { Value.m_Value = OutputType{}; Gradient.m_Value.Fill(OutputRealType{}); Hessian.m_Value.Fill(OutputRealType{}); Laplacian.m_Value = OutputRealType{}; GradientNorm.m_Value = OutputRealType{}; MeanCurvature.m_Value = OutputRealType{}; ForwardGradient.m_Value.Fill(OutputRealType{}); BackwardGradient.m_Value.Fill(OutputRealType{}); } LevelSetDataType(const LevelSetDataType & iData) : Value(iData.Value) , Gradient(iData.Gradient) , Hessian(iData.Hessian) , Laplacian(iData.Laplacian) , GradientNorm(iData.GradientNorm) , MeanCurvature(iData.MeanCurvature) , ForwardGradient(iData.ForwardGradient) , BackwardGradient(iData.BackwardGradient) {} ~LevelSetDataType() = default; void operator=(const LevelSetDataType & iData) { Value = iData.Value; Gradient = iData.Gradient; Hessian = iData.Hessian; Laplacian = iData.Laplacian; GradientNorm = iData.GradientNorm; MeanCurvature = iData.MeanCurvature; ForwardGradient = iData.ForwardGradient; BackwardGradient = iData.BackwardGradient; } /** the boolean value stores if it has already been computed */ DataType Value; DataType Gradient; DataType Hessian; DataType Laplacian; DataType GradientNorm; DataType MeanCurvature; DataType ForwardGradient; DataType BackwardGradient; }; virtual void Evaluate(const InputType & iP, LevelSetDataType & ioData) const = 0; virtual void EvaluateGradient(const InputType & iP, LevelSetDataType & ioData) const = 0; virtual void EvaluateHessian(const InputType & iP, LevelSetDataType & ioData) const = 0; virtual void EvaluateLaplacian(const InputType & iP, LevelSetDataType & ioData) const = 0; virtual void EvaluateGradientNorm(const InputType & iP, LevelSetDataType & ioData) const; virtual void EvaluateMeanCurvature(const InputType & iP, LevelSetDataType & ioData) const; virtual void EvaluateForwardGradient(const InputType & iP, LevelSetDataType & ioData) const = 0; virtual void EvaluateBackwardGradient(const InputType & iP, LevelSetDataType & ioData) const = 0; /** Returns true if iP is inside the level set, i.e. \f$\phi(p) \le 0 \f$ */ virtual bool IsInside(const InputType & iP) const; /** Get the maximum number of regions that this data can be * separated into. */ itkGetConstMacro(MaximumNumberOfRegions, RegionType); /** Initialize the level set function */ void Initialize() override; /** Methods to manage streaming. */ void UpdateOutputInformation() override; void SetRequestedRegionToLargestPossibleRegion() override; void CopyInformation(const DataObject * data) override; void Graft(const DataObject * data) override; bool RequestedRegionIsOutsideOfTheBufferedRegion() override; bool VerifyRequestedRegion() override; /** Set the requested region from this data object to match the requested * region of the data object passed in as a parameter. This method * implements the API from DataObject. The data object parameter must be * castable to a PointSet. */ void SetRequestedRegion(const DataObject * data) override; /** Set/Get the Requested region */ virtual void SetRequestedRegion(const RegionType & region); itkGetConstMacro(RequestedRegion, RegionType); /** Set/Get the Buffered region */ virtual void SetBufferedRegion(const RegionType & region); itkGetConstMacro(BufferedRegion, RegionType); protected: LevelSetBase(); ~LevelSetBase() override = default; // If the RegionType is ITK_UNSTRUCTURED_REGION, then the following // variables represent the maximum number of region that the data // object can be broken into, which region out of how many is // currently in the buffered region, and the number of regions and // the specific region requested for the update. Data objects that // do not support any division of the data can simply leave the // MaximumNumberOfRegions as 1. The RequestedNumberOfRegions and // RequestedRegion are used to define the currently requested // region. The LargestPossibleRegion is always requested region = 0 // and number of regions = 1; RegionType m_MaximumNumberOfRegions{ 0 }; RegionType m_NumberOfRegions{ 0 }; RegionType m_RequestedNumberOfRegions{ 0 }; RegionType m_BufferedRegion{ 0 }; RegionType m_RequestedRegion{ 0 }; }; } // namespace itk #ifndef ITK_MANUAL_INSTANTIATION # include "itkLevelSetBase.hxx" #endif #endif // itkLevelSetBase_h