#pragma once#include"itkParticleEntropyGradientFunction.h"#include"ParticleImageDomainWithGradients.h"#include"ParticleImageDomainWithCurvature.h"#include"itkParticleMeanCurvatureAttribute.h"#include"itkCommand.h"#include<fstream>#include<math.h>#include"itkMath.h"#define NBHD_SIGMA_FACTOR 1.3namespaceitk{template<classTGradientNumericType,unsignedintVDimension>classParticleConstrainedModifiedCotangentEntropyGradientFunction:publicParticleEntropyGradientFunction<TGradientNumericType,VDimension>{public:typedefParticleConstrainedModifiedCotangentEntropyGradientFunctionSelf;typedefSmartPointer<Self>Pointer;typedefSmartPointer<constSelf>ConstPointer;typedefParticleEntropyGradientFunction<TGradientNumericType,VDimension>Superclass;itkTypeMacro(ParticleConstrainedModifiedCotangentEntropyGradientFunction,ParticleEntropyGradientFunction);typedeftypenameSuperclass::GradientNumericTypeGradientNumericType;typedeftypenameSuperclass::ParticleSystemTypeParticleSystemType;typedeftypenameSuperclass::VectorTypeVectorType;typedeftypenameSuperclass::PointTypePointType;typedeftypenameSuperclass::GradientVectorTypeGradientVectorType;typedeftypenameshapeworks::ParticleImageDomainWithCurvature<TGradientNumericType>::VnlMatrixTypeVnlMatrixType;itkNewMacro(Self);itkStaticConstMacro(Dimension,unsignedint,VDimension);inlinevirtualVectorTypeEvaluate(unsignedinta,unsignedintb,constParticleSystemType*c,double&d)const{doublee;returnthis->Evaluate(a,b,c,d,e);}virtualVectorTypeEvaluate(unsignedint,unsignedint,constParticleSystemType*,double&,double&)const;virtualvoidBeforeEvaluate(unsignedint,unsignedint,constParticleSystemType*);inlinevirtualdoubleEnergy(unsignedinta,unsignedintb,constParticleSystemType*c)const{doubled,e;this->Evaluate(a,b,c,d,e);returne;}virtualvoidAfterIteration(){}virtualvoidBeforeIteration(){// compute the global sigma for the whole particle system using its current status (particles position)if(m_RunStatus==1)// initialization{// allow sigma to change during initialization only when particles are increaseddoubleoldSigma=m_GlobalSigma;this->EstimateGlobalSigma(this->GetParticleSystem());if(m_GlobalSigma>=0.0)// make sure that we update the global sigma at the beginning (in the constructor, it is -1){if((abs(oldSigma-m_GlobalSigma)/m_GlobalSigma)<0.1){// not that much change, probably same number of particles, don't change the global sigmam_GlobalSigma=oldSigma;}}}else// optimization{if(m_GlobalSigma<0.0)// only compute sigma once during optimizationthis->EstimateGlobalSigma(this->GetParticleSystem());}// std::cout << "m_GlobalSigma: " << m_GlobalSigma << std::endl;}voidEstimateGlobalSigma(constParticleSystemType*system);inlinedoubleComputeModifiedCotangent(doublerij)const{if(rij>m_GlobalSigma)return0.0;constdoubleepsilon=1.0e-6;doubler=itk::Math::pi_over_2*rij/(m_GlobalSigma+epsilon);doublecotan=cos(r)/(sin(r)+epsilon);doubleval=cotan+r-itk::Math::pi_over_2;returnval;}inlinedoubleComputeModifiedCotangentDerivative(doublerij)const{if(rij>m_GlobalSigma)return0.0;constdoubleepsilon=1.0e-6;doubler=itk::Math::pi_over_2*rij/(m_GlobalSigma+epsilon);doublesin_2=1.0/(pow(sin(r),2.0)+epsilon);doubleval=-1.0*(itk::Math::pi_over_2*(1.0/(m_GlobalSigma+epsilon)))*(1-sin_2);returnval;}voidSetDomainsPerShape(inti){m_DomainsPerShape=i;}intGetDomainsPerShape()const{returnm_DomainsPerShape;}// set/get run status : 1 for initialization and 2 for optimizationvoidSetRunStatus(inti){m_RunStatus=i;}intGetRunStatus()const{returnm_RunStatus;}voidSetDiagnosticsOutputPrefix(conststd::strings){m_diagnostics_prefix=s;}virtualtypenameParticleVectorFunction<VDimension>::PointerClone(){typenameParticleConstrainedModifiedCotangentEntropyGradientFunction<TGradientNumericType,VDimension>::Pointercopy=ParticleConstrainedModifiedCotangentEntropyGradientFunction<TGradientNumericType,VDimension>::New();copy->SetParticleSystem(this->GetParticleSystem());copy->m_Counter=this->m_Counter;copy->m_CurrentWeights=this->m_CurrentWeights;copy->m_CurrentNeighborhood=this->m_CurrentNeighborhood;copy->m_GlobalSigma=this->m_GlobalSigma;copy->m_MinimumNeighborhoodRadius=this->m_MinimumNeighborhoodRadius;copy->m_MaximumNeighborhoodRadius=this->m_MaximumNeighborhoodRadius;copy->m_FlatCutoff=this->m_FlatCutoff;copy->m_NeighborhoodToSigmaRatio=this->m_NeighborhoodToSigmaRatio;copy->m_DomainNumber=this->m_DomainNumber;copy->m_ParticleSystem=this->m_ParticleSystem;copy->m_DomainsPerShape=this->m_DomainsPerShape;copy->m_diagnostics_prefix=this->m_diagnostics_prefix;copy->m_RunStatus=this->m_RunStatus;return(typenameParticleVectorFunction<VDimension>::Pointer)copy;}protected:ParticleConstrainedModifiedCotangentEntropyGradientFunction():m_Counter(0),m_DomainsPerShape(1),m_GlobalSigma(-1.0){}virtual~ParticleConstrainedModifiedCotangentEntropyGradientFunction(){}voidoperator=(constParticleConstrainedModifiedCotangentEntropyGradientFunction&);ParticleConstrainedModifiedCotangentEntropyGradientFunction(constParticleConstrainedModifiedCotangentEntropyGradientFunction&);unsignedintm_Counter;//double m_CurrentSigma;typenameParticleSystemType::PointVectorTypem_CurrentNeighborhood;std::vector<double>m_CurrentWeights;std::stringm_diagnostics_prefix;intm_DomainsPerShape;intm_RunStatus;// 1 for initialization and 2 for optimizationdoublem_GlobalSigma;floatm_MaxMoveFactor;};}//end namespace#include"itkParticleConstrainedModifiedCotangentEntropyGradientFunction.txx"