#pragma once#include<itkObjectFactory.h>#include<vtkCellLocator.h>#include<vtkGenericCell.h>#include<vtkLine.h>#include<vtkPolyData.h>#include<Eigen/Dense>#include"ParticleDomain.h"namespaceshapeworks{classContourDomain:publicParticleDomain{public:usingPointer=std::shared_ptr<ContourDomain>;explicitContourDomain(){}virtual~ContourDomain(){}voidSetPolyLine(vtkSmartPointer<vtkPolyData>poly_data);DomainTypeGetDomainType()constoverride{returnDomainType::Contour;}virtualboolApplyConstraints(PointType&p,intidx,booldbg=false)constoverride;virtualPointTypeUpdateParticlePosition(constPointType&point,intidx,VectorDoubleType&update)constoverride;virtualVectorDoubleTypeProjectVectorToSurfaceTangent(VectorDoubleType&gradE,constPointType&pos,intidx)constoverride;virtualVectorFloatTypeSampleNormalAtPoint(constPointType&point,intidx)constoverride{throwstd::runtime_error("Contours do not have normals");}virtualVectorFloatTypeSampleGradientAtPoint(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,VectorDoubleType*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?}voidInvalidateParticlePosition(intidx)constoverride;PointTypeGetPositionAfterSplit(constPointType&pt,constVectorDoubleType&local_direction,constVectorDoubleType&global_direction,doubleepsilon)constoverride;private: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;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;doubleavg_edge_length_{0.0};voidComputeBounds();voidComputeGeodesics(vtkSmartPointer<vtkPolyData>poly_data);voidComputeAvgEdgeLength();intGetLineForPoint(constdoublept[3],intidx,double&closest_distance,doubleclosest_pt[3])const;};}// namespace shapeworks