#pragma once#include"vnl/vnl_vector_fixed.h"#include"TriMesh.h"#include"KDtree.h"#include"MeshWrapper.h"#include<Eigen/Core>#include<Eigen/Geometry>#include<vector>namespaceshapeworks{classTriMeshWrapper:publicMeshWrapper{public:explicitTriMeshWrapper(std::shared_ptr<trimesh::TriMesh>mesh);~TriMeshWrapper()=default;typedeftypenameMeshWrapper::PointTypePointType;typedeftypenameMeshWrapper::GradNTypeGradNType;doubleComputeDistance(constPointType&pointa,intidx_a,constPointType&pointb,intidx_b,vnl_vector_fixed<double,3>*out_grad)constoverride;PointTypeGeodesicWalk(PointTypepointa,intidx,vnl_vector_fixed<double,DIMENSION>vector)constoverride;vnl_vector_fixed<double,DIMENSION>ProjectVectorToSurfaceTangent(constPointType&pointa,intidx,vnl_vector_fixed<double,DIMENSION>&vector)constoverride;vnl_vector_fixed<float,DIMENSION>SampleNormalAtPoint(PointTypep,intidx)constoverride;GradNTypeSampleGradNAtPoint(PointTypep,intidx)constoverride;PointTypeSnapToMesh(PointTypepointa,intidx)constoverride;PointTypeGetPointOnMesh()constoverride;inlineconstPointType&GetMeshLowerBound()constoverride{returnmesh_lower_bound_;}inlineconstPointType&GetMeshUpperBound()constoverride{returnmesh_upper_bound_;}boolIsGeodesicsEnabled()constoverride{returnfalse;}inlinevtkSmartPointer<vtkPolyData>GetPolydata()constoverride{returnvtkSmartPointer<vtkPolyData>();}private:Eigen::Vector3dGeodesicWalkOnFace(Eigen::Vector3dpoint_a,Eigen::Vector3dprojected_vector,intface_index)const;Eigen::Vector3dProjectVectorToFace(constEigen::Vector3d&normal,constEigen::Vector3d&vector)const;Eigen::Vector3dRotateVectorToFace(constEigen::Vector3d&prev_normal,constEigen::Vector3d&next_normal,constEigen::Vector3d&vector)const;constEigen::Vector3dGetFaceNormal(intface_index)const;voidComputeMeshBounds();voidComputeGradN();// Gradient of normalstrimesh::pointGetBarycentricIntersection(trimesh::vec3start,trimesh::vec3end,intcurrentFace,intedge)const;intGetNearestVertex(trimesh::pointpt)const;intGetTriangleForPoint(trimesh::pointpt,intidx,trimesh::vec&bary)const;std::vector<int>GetKNearestVertices(trimesh::pointpt,intk)const;trimesh::vec3ComputeBarycentricCoordinates(trimesh::pointpt,intface)const;staticinlineboolIsBarycentricCoordinateValid(consttrimesh::vec3&b);// IGL Helper functionsvoidGetIGLMesh(Eigen::MatrixXd&V,Eigen::MatrixXi&F);std::shared_ptr<trimesh::TriMesh>mesh_;std::shared_ptr<trimesh::KDtree>kd_tree_;// Maintains a map of particle index -> triangle index// Has to be mutable because all of the accessor APIs are constmutablestd::vector<int>particle2tri_;std::vector<GradNType>grad_normals_;PointTypemesh_lower_bound_;PointTypemesh_upper_bound_;};}