#pragma once#include"ParticleImageDomainWithCurvature.h"#include"TriMesh.h"#include"TriMesh_algo.h"#include"meshFIM.h"#include"vnl/vnl_cross.h"#include"vnl/vnl_inverse.h"#include"vnl/vnl_math.h"namespaceshapeworks{template<classT>classParticleImplicitSurfaceDomain:publicParticleImageDomainWithCurvature<T>{public:typedefParticleImageDomainWithCurvature<T>Superclass;typedefstd::shared_ptr<ParticleImplicitSurfaceDomain>Pointer;typedeftypenameSuperclass::ImageTypeImageType;typedeftypenameSuperclass::PointTypePointType;virtualvoidSetTolerance(constT_Tolerance){if(this->m_Tolerance!=_Tolerance){this->m_Tolerance=_Tolerance;// this->Modified();}}virtualTGetTolerance(){returnthis->m_Tolerance;}shapeworks::DomainTypeGetDomainType()constoverride{returnshapeworks::DomainType::Image;}virtualboolApplyConstraints(PointType&p,intidx,booldbg=false)constoverride{// First apply and constraints imposed by superclasses. This will// guarantee the point starts in the correct image domain.boolflag=Superclass::ApplyConstraints(p);unsignedintk=0;doublemult=1.0;constTepsilon=m_Tolerance*0.001;Tf=this->Sample(p);Tgradmag=1.0;while(fabs(f)>(m_Tolerance*mult)||gradmag<epsilon)// while ( fabs(f) > m_Tolerance || gradmag < epsilon){PointTypep_old=p;// vnl_vector_fixed<T, DIMENSION> grad = -this->SampleGradientAtPoint(p);vnl_vector_fixed<T,DIMENSION>gradf=this->SampleGradientAtPoint(p,idx);vnl_vector_fixed<double,DIMENSION>grad;grad[0]=double(gradf[0]);grad[1]=double(gradf[1]);grad[2]=double(gradf[2]);gradmag=grad.magnitude();// vnl_vector_fixed<T, DIMENSION> vec = grad * (f / (gradmag + epsilon));vnl_vector_fixed<double,DIMENSION>vec=grad*(double(f)/(gradmag+double(epsilon)));for(unsignedinti=0;i<DIMENSION;i++){p[i]-=vec[i];}f=this->Sample(p);// Raise the tolerance if we have done too many iterations.k++;if(k>10000){mult*=2.0;k=0;}}// end whilereturnflag;};inlinePointTypeUpdateParticlePosition(constPointType&point,intidx,vnl_vector_fixed<double,DIMENSION>&update)constoverride{PointTypenewpoint;// Master merge conflict// vnl_vector_fixed<float, DIMENSION> negativeUpdate;// for (unsigned int i = 0; i < DIMENSION; i++) { negativeUpdate[i] = -update[i]; }// for (unsigned int i = 0; i < DIMENSION; i++) { newpoint[i] = point[i] + negativeUpdate[i]; }for(unsignedinti=0;i<3;i++){newpoint[i]=point[i]-update[i];}// for (unsigned int i = 0; i < DIMENSION; i++) { newpoint[i] = point[i] - update[i]; }// debugggApplyConstraints(newpoint,idx);// debuggg/* if(!this->GetConstraints()->IsAnyViolated(point) && this->GetConstraints()->IsAnyViolated(newpoint)){ std::cerr << "####### Violation within apply constraints #######" << std::endl; } *//* if(point[2] >= 0 && newpoint[2] < 0){ std::cerr << "NewPoint " << newpoint << std::endl; std::cerr << "Point " << point << std::endl; std::cerr << "Update " << update << std::endl; } */returnnewpoint;}voidSetMesh(TriMesh*mesh){m_mesh=newmeshFIM();m_mesh->SetMesh(mesh);};voidSetFeaMesh(constchar*feaFile){m_mesh->ReadFeatureFromFile(feaFile);};voidSetFeaGrad(constchar*feaGradFile){m_mesh->ReadFeatureGradientFromFile(feaGradFile);};voidSetFids(constchar*fidsFile){m_mesh->ReadFaceIndexMap(fidsFile);consttypenameImageType::PointTypeorgn=this->GetOrigin();m_mesh->imageOrigin[0]=orgn[0];m_mesh->imageOrigin[1]=orgn[1];m_mesh->imageOrigin[2]=orgn[2];typenameImageType::RegionType::SizeTypesz=this->GetSize();m_mesh->imageSize[0]=sz[0];m_mesh->imageSize[1]=sz[1];m_mesh->imageSize[2]=sz[2];typenameImageType::SpacingTypesp=this->GetSpacing();m_mesh->imageSpacing[0]=sp[0];m_mesh->imageSpacing[1]=sp[1];m_mesh->imageSpacing[2]=sp[2];typenameImageType::RegionType::IndexTypeidx=this->GetIndex();m_mesh->imageIndex[0]=idx[0];m_mesh->imageIndex[1]=idx[1];m_mesh->imageIndex[2]=idx[2];};meshFIM*GetMesh(){returnm_mesh;}meshFIM*GetMesh()const{returnm_mesh;}PointTypeGetZeroCrossingPoint()constoverride{PointTypep;// TODO Hong// Return point that doesn't violate plane constraints.returnp;}ParticleImplicitSurfaceDomain():m_Tolerance(1.0e-4){m_mesh=NULL;}voidPrintSelf(std::ostream&os,itk::Indentindent)const{Superclass::PrintSelf(os,indent);os<<indent<<"m_Tolerance = "<<m_Tolerance<<std::endl;}virtual~ParticleImplicitSurfaceDomain(){};private:Tm_Tolerance;meshFIM*m_mesh;};}// end namespace shapeworks