/*========================================================================= 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"ParticleImageDomain.h"#include"itkGradientImageFilter.h"#include"itkFixedArray.h"namespaceshapeworks{template<classT>classParticleImageDomainWithGradients:publicParticleImageDomain<T>{public:usingPointer=std::shared_ptr<ParticleImageDomainWithGradients<T>>;typedeftypenameParticleImageDomain<T>::PointTypePointType;typedeftypenameParticleImageDomain<T>::ImageTypeImageType;typedefitk::FixedArray<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,itk::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{std::ostringstreammessage;\
message<<"Gradient queried for a Point, "<<p<<", outside the given image domain.";throwstd::runtime_error(message.str());}}openvdb::VectorGrid::Ptrm_VDBGradient;};}// end namespace itk