/*========================================================================= 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"ParticleImageDomainWithGradN.h"#include"itkImageRegionIteratorWithIndex.h"#include"itkImageRegionIterator.h"#include"itkDiscreteGaussianImageFilter.h"namespaceshapeworks{template<classT>classParticleImageDomainWithCurvature:publicParticleImageDomainWithGradN<T>{public:typedefParticleImageDomainWithGradN<T>Superclass;typedeftypenameSuperclass::PointTypePointType;typedeftypenameSuperclass::ImageTypeImageType;typedeftypenameSuperclass::VnlMatrixTypeVnlMatrixType;voidSetImage(ImageType*I,doublenarrow_band){// Computes partial derivatives in parent classSuperclass::SetImage(I,narrow_band);m_VDBCurvature=openvdb::tools::meanCurvature(*this->GetVDBImage());this->ComputeSurfaceStatistics(I);}doubleGetCurvature(constPointType&p,intidx)constoverride{if(this->m_FixedDomain){return0;}constautocoord=this->ToVDBCoord(p);returnopenvdb::tools::BoxSampler::sample(m_VDBCurvature->tree(),coord);}inlinedoubleGetSurfaceMeanCurvature()constoverride{returnm_SurfaceMeanCurvature;}inlinedoubleGetSurfaceStdDevCurvature()constoverride{returnm_SurfaceStdDevCurvature;}protected:ParticleImageDomainWithCurvature(){}voidPrintSelf(std::ostream&os,itk::Indentindent)const{Superclass::PrintSelf(os,indent);os<<indent<<"VDB Active Voxels = "<<m_VDBCurvature->activeVoxelCount()<<std::endl;}virtual~ParticleImageDomainWithCurvature(){};private:openvdb::FloatGrid::Ptrm_VDBCurvature;// Cache surface statisticsdoublem_SurfaceMeanCurvature;doublem_SurfaceStdDevCurvature;voidComputeSurfaceStatistics(ImageType*I){// TODO: This computation is copied from itkParticleMeanCurvatureAttribute// Since the entire Image is not available after the initial load, its simplest// to calculate it now. But it should be a part of itkParticleMeanCurvatureAttribute// Loop through a zero crossing image, project all the zero crossing points// to the surface, and use those points to comput curvature stats.typedefitk::ZeroCrossingImageFilter<ImageType,ImageType>ZeroCrossingImageFilterType;typenameZeroCrossingImageFilterType::Pointerzc=ZeroCrossingImageFilterType::New();zc->SetInput(I);zc->Update();itk::ImageRegionConstIteratorWithIndex<ImageType>it(zc->GetOutput(),zc->GetOutput()->GetRequestedRegion());std::vector<double>datalist;m_SurfaceMeanCurvature=0.0;m_SurfaceStdDevCurvature=0.0;for(;!it.IsAtEnd();++it){if(it.Get()==1.0){// Find closest pixel location to surface.PointTypepos;//dynamic_cast<const DomainType//*>(system->GetDomain(d))->GetImage()->TransformIndexToPhysicalPoint(it.GetIndex(), pos);I->TransformIndexToPhysicalPoint(it.GetIndex(),pos);// Project point to surface.// Make sure constraints are enabled// bool c = domain->GetConstraintsEnabled();// domain->EnableConstraints();this->ApplyConstraints(pos);// domain->SetConstraintsEnabled(c);// Compute curvature at point.// std::cout << "pos : " << pos[0] << ' ' << pos[1] << ' ' << pos[2] << std::endl;doublemc=this->GetCurvature(pos,-1);m_SurfaceMeanCurvature+=mc;datalist.push_back(mc);}}doublen=static_cast<double>(datalist.size());m_SurfaceMeanCurvature/=n;// Compute std deviation using point listfor(unsignedinti=0;i<datalist.size();i++){m_SurfaceStdDevCurvature+=(datalist[i]-m_SurfaceMeanCurvature)*(datalist[i]-m_SurfaceMeanCurvature);}m_SurfaceStdDevCurvature=sqrt(m_SurfaceStdDevCurvature/(n-1));}};}// end namespace itk