/*========================================================================= Copyright (c) 2009 Scientific Computing and Imaging Institute. See ShapeWorksLicense.txt for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information.=========================================================================*/#pragma once#include"itkDataObject.h"#include"itkPoint.h"#include"vnl/vnl_vector_fixed.h"#include"vnl/vnl_matrix_fixed.h"#include"DomainType.h"#include"Constraints.h"namespaceitk{classParticleDomain:publicDataObject{public:typedefSmartPointer<ParticleDomain>Pointer;typedefPoint<double,DIMENSION>PointType;typedefvnl_matrix_fixed<float,DIMENSION,DIMENSION>GradNType;virtualboolApplyConstraints(PointType&p,intidx,booldbg=false)const=0;//todo update should be const?virtualPointTypeUpdateParticlePosition(constPointType&point,intidx,vnl_vector_fixed<double,DIMENSION>&update)const=0;virtualvoidInvalidateParticlePosition(intidx)const{}virtualvnl_vector_fixed<double,DIMENSION>ProjectVectorToSurfaceTangent(vnl_vector_fixed<double,DIMENSION>&gradE,constPointType&pos,intidx)const=0;virtualvnl_vector_fixed<float,DIMENSION>SampleGradientAtPoint(constPointType&point,intidx)const=0;virtualvnl_vector_fixed<float,DIMENSION>SampleNormalAtPoint(constPointType&point,intidx)const=0;virtualGradNTypeSampleGradNAtPoint(constPointType&p,intidx)const=0;virtualdoubleDistance(constPointType&a,intidx_a,constPointType&b,intidx_b,vnl_vector_fixed<double,DIMENSION>*out_grad=nullptr)const{if(out_grad!=nullptr){for(inti=0;i<DIMENSION;i++){(*out_grad)[i]=a[i]-b[i];}}returna.EuclideanDistanceTo(b);}virtualdoubleSquaredDistance(constPointType&a,intidx_a,constPointType&b,intidx_b)const{returna.SquaredEuclideanDistanceTo(b);}virtualboolIsWithinDistance(constPointType&a,intidx_a,constPointType&b,intidx_b,doubletest_dist,double&distance)const{distance=this->Distance(a,idx_a,b,idx_b);returndistance<test_dist;}virtualdoubleGetCurvature(constPointType&p,intidx)const=0;virtualdoubleGetSurfaceMeanCurvature()const=0;virtualdoubleGetSurfaceStdDevCurvature()const=0;virtualconstPointType&GetLowerBound()const=0;virtualconstPointType&GetUpperBound()const=0;virtualPointTypeGetZeroCrossingPoint()const=0;virtualdoubleGetSurfaceArea()const=0;virtualPointTypeGetValidLocationNear(PointTypep)const=0;virtualdoubleGetMaxDiameter()const=0;virtualvoidDeleteImages()=0;virtualvoidDeletePartialDerivativeImages()=0;virtualvoidUpdateZeroCrossingPoint()=0;boolIsDomainFixed()const{returnm_FixedDomain;}virtualshapeworks::DomainTypeGetDomainType()const=0;std::shared_ptr<Constraints>GetConstraints()const{returnconstraints;}// Use `random` to advance a particle and return a new positionvirtualPointTypeGetPositionAfterSplit(constPointType&pt,constvnl_vector_fixed<double,3>&random,doubleepsilon)const{// todo this has been copied from itkParticleSystem::AdvancedAllParticleSplitting.// Ideally, we should compute a direction that is "consistent" depending on the domain type and use the// `UpdateParticlePosition` API to advance the particle. See ContourDomain for an example. Leaving this be for// now because we'd have to retest all MeshDomain and ImageDomain use cases if this behaviour changes.PointTypenew_pt;for(unsignedintk=0;k<3;k++){new_pt[k]=pt[k]+epsilon*random[k]/5.;}returnnew_pt;}voidSetDomainID(intid){this->m_DomainID=id;}voidSetDomainName(std::stringname){this->m_DomainName=name;}protected:// is this a fixed domain or not? We start as fixed and if an image or mesh is set, we set this to falseboolm_FixedDomain{true};intm_DomainID{-1};std::stringm_DomainName;ParticleDomain(){this->constraints=std::make_shared<Constraints>();}virtual~ParticleDomain(){}voidPrintSelf(std::ostream&os,Indentindent)const{Superclass::PrintSelf(os,indent);}std::shared_ptr<Constraints>constraints;private:ParticleDomain(constParticleDomain&);//purposely not implementedvoidoperator=(constParticleDomain&);//purposely not implemented};}// end namespace itk