/*========================================================================= 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"itkImage.h"#include"itkImageDuplicator.h"#include"itkParticleImageDomain.h"#include"itkGradientImageFilter.h"#include"itkFixedArray.h"namespaceitk{template<classT>classParticleImageDomainWithGradients:publicParticleImageDomain<T>{public:typedefSmartPointer<ParticleImageDomainWithGradients<T>>Pointer;typedeftypenameParticleImageDomain<T>::PointTypePointType;typedeftypenameParticleImageDomain<T>::ImageTypeImageType;typedefFixedArray<T,DIMENSION>VectorType;typedefvnl_vector_fixed<T,DIMENSION>VnlVectorType;voidSetImage(ImageType*I,doublenarrow_band){ParticleImageDomain<T>::SetImage(I,narrow_band);m_VDBGradient=openvdb::tools::gradient(*this->GetVDBImage());}inlinevnl_vector_fixed<float,DIMENSION>SampleGradientAtPoint(constPointType&p,intidx)const{returnthis->SampleGradientVnl(p,idx);}inlinevnl_vector_fixed<float,DIMENSION>SampleNormalAtPoint(constPointType&p,intidx)const{vnl_vector_fixed<float,DIMENSION>grad=this->SampleGradientVnl(p,idx);returngrad.normalize();}vnl_vector_fixed<double,DIMENSION>ProjectVectorToSurfaceTangent(vnl_vector_fixed<double,DIMENSION>&gradE,constPointType&pos,intidx)constoverride{doubledotprod=0.0;VnlVectorTypenormal=this->SampleNormalAtPoint(pos,idx);for(unsignedinti=0;i<DIMENSION;i++){dotprod+=normal[i]*gradE[i];}vnl_vector_fixed<double,DIMENSION>result;for(unsignedinti=0;i<DIMENSION;i++){result[i]=gradE[i]-normal[i]*dotprod;}returnresult;}voidDeleteImages()override{ParticleImageDomain<T>::DeleteImages();m_VDBGradient=0;}protected:ParticleImageDomainWithGradients(){}virtual~ParticleImageDomainWithGradients(){}voidPrintSelf(std::ostream&os,Indentindent)const{ParticleImageDomain<T>::PrintSelf(os,indent);os<<indent<<"VDB Active Voxels = "<<m_VDBGradient->activeVoxelCount()<<std::endl;}openvdb::VectorGrid::PtrGetVDBGradient(){returnm_VDBGradient;}private:inlineVnlVectorTypeSampleGradientVnl(constPointType&p,intidx)const{returnVnlVectorType(this->SampleGradient(p,idx).GetDataPointer());}inlineVectorTypeSampleGradient(constPointType&p,intidx)const{if(this->IsInsideBuffer(p)){constautocoord=this->ToVDBCoord(p);constauto_v=openvdb::tools::BoxSampler::sample(m_VDBGradient->tree(),coord);constVectorTypev(_v.asPointer());// This copies 3 floats from a VDB vector to a vnl vectorreturnv;}else{itkExceptionMacro("Gradient queried for a Point, "<<p<<", outside the given image domain.");}}openvdb::VectorGrid::Ptrm_VDBGradient;};}// end namespace itk