/*========================================================================= 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"itkParticleDomain.h"#include<Eigen/Dense>#include<vtkPolyData.h>#include<vtkLine.h>#include<vtkGenericCell.h>#include<vtkCellLocator.h>#include<itkObjectFactory.h>namespaceitk{classContourDomain:publicParticleDomain{public:typedefSmartPointer<ContourDomain>Pointer;itkSimpleNewMacro(ContourDomain);typedeftypenameParticleDomain::PointTypePointType;explicitContourDomain(){}virtual~ContourDomain(){}voidSetPolyLine(vtkSmartPointer<vtkPolyData>poly_data);shapeworks::DomainTypeGetDomainType()constoverride{returnshapeworks::DomainType::Contour;}virtualboolApplyConstraints(PointType&p,intidx,booldbg=false)constoverride;virtualPointTypeUpdateParticlePosition(constPointType&point,intidx,vnl_vector_fixed<double,DIMENSION>&update)constoverride;virtualvnl_vector_fixed<double,DIMENSION>ProjectVectorToSurfaceTangent(vnl_vector_fixed<double,DIMENSION>&gradE,constPointType&pos,intidx)constoverride;virtualvnl_vector_fixed<float,DIMENSION>SampleNormalAtPoint(constPointType&point,intidx)constoverride{throwstd::runtime_error("Contours do not have normals");}virtualvnl_vector_fixed<float,DIMENSION>SampleGradientAtPoint(constPointType&point,intidx)constoverride{throwstd::runtime_error("Contours do not have gradients");}virtualGradNTypeSampleGradNAtPoint(constPointType&p,intidx)constoverride{throwstd::runtime_error("Contours do not have gradient of normals");}virtualPointTypeGetValidLocationNear(PointTypep)constoverride{this->ApplyConstraints(p,-1);returnp;}virtualdoubleGetMaxDiameter()constoverride{//todo copied from MeshDomain: should this not be the length of the bounding box diagonal?constPointTypebb=upper_bound_-lower_bound_;returnstd::max({bb[0],bb[1],bb[2]});}virtualvoidUpdateZeroCrossingPoint()override{}doubleGetCurvature(constPointType&p,intidx)constoverride{returnGetSurfaceMeanCurvature();}virtualdoubleGetSurfaceMeanCurvature()constoverride{// This function is used by MeanCurvatureAttribute which is used for good/bad assessment// These arbitrary values should eventually be replaced with actual computationreturn0.15;}virtualdoubleGetSurfaceStdDevCurvature()constoverride{// This function is used by MeanCurvatureAttribute which is used for good/bad assessment// These arbitrary values should eventually be replaced with actual computationreturn0.02;}doubleDistance(constPointType&a,intidx_a,constPointType&b,intidx_b,vnl_vector_fixed<double,3>*out_grad=nullptr)constoverride;doubleSquaredDistance(constPointType&a,intidx_a,constPointType&b,intidx_b)constoverride;constPointType&GetLowerBound()constoverride{returnlower_bound_;}constPointType&GetUpperBound()constoverride{returnupper_bound_;}PointTypeGetZeroCrossingPoint()constoverride{PointTypeout;doubledist;intclosest_line=GetLineForPoint(upper_bound_.GetDataPointer(),-1,dist,out.GetDataPointer());returnout;}doubleGetSurfaceArea()constoverride{throwstd::runtime_error("Contours do not have area");}voidDeleteImages()override{// TODO what?}voidDeletePartialDerivativeImages()override{// TODO what?}virtualvoidInvalidateParticlePosition(intidx)constoverride;virtualPointTypeGetPositionAfterSplit(constPointType&pt,constvnl_vector_fixed<double,3>&random,doubleepsilon)constoverride;protected:voidPrintSelf(std::ostream&os,Indentindent)constoverride{DataObject::Superclass::PrintSelf(os,indent);os<<indent<<"ContourDomain\n";}private:PointTypelower_bound_,upper_bound_;vtkSmartPointer<vtkPolyData>poly_data_;vtkSmartPointer<vtkCellLocator>cell_locator_;std::vector<vtkSmartPointer<vtkLine>>lines_;// Geodesics between all point pairs. Assumes the number of points is very smallEigen::MatrixXdgeodesics_;// cache which line a particle is onmutablestd::vector<int>particle_lines_;// store some information about the last geodesic query. The next one will most likely reuse thismutableintgeo_lq_idx_=-1;mutableintgeo_lq_line_=-1;mutabledoublegeo_lq_dist_=-1;voidComputeBounds();voidComputeGeodesics(vtkSmartPointer<vtkPolyData>poly_data);intGetLineForPoint(constdoublept[3],intidx,double&closest_distance,doubleclosest_pt[3])const;doubleComputeLineCoordinate(constdoublept[3],intline)const;// Return the number of lines that consist of i-th pointintNumberOfLinesIncidentOnPoint(inti)const;PointTypeGeodesicWalk(constPointType&start_pt,intidx,constEigen::Vector3d&update_vec)const;intNumberOfLines()const;intNumberOfPoints()const;Eigen::Vector3dGetPoint(intid)const;};}// end namespace itk