| 7 | using namespace PyMesh; |
| 8 | |
| 9 | void VertexLaplacianAttribute::compute_from_mesh(Mesh& mesh) { |
| 10 | const size_t dim = mesh.get_dim(); |
| 11 | const size_t num_vertices = mesh.get_num_vertices(); |
| 12 | const size_t num_faces = mesh.get_num_faces(); |
| 13 | const size_t vertex_per_face = mesh.get_vertex_per_face(); |
| 14 | |
| 15 | if (vertex_per_face != 3) { |
| 16 | throw NotImplementedError( |
| 17 | "Only triangle Laplacian is supported for now."); |
| 18 | } |
| 19 | |
| 20 | VectorF& laplacian = m_values; |
| 21 | laplacian = VectorF::Zero(num_vertices * dim); |
| 22 | for (size_t i=0; i<num_faces; i++) { |
| 23 | VectorI face = mesh.get_face(i); |
| 24 | VectorF v0 = mesh.get_vertex(face[0]); |
| 25 | VectorF v1 = mesh.get_vertex(face[1]); |
| 26 | VectorF v2 = mesh.get_vertex(face[2]); |
| 27 | assert(face.size() == vertex_per_face); |
| 28 | VectorF cotan_weights = compute_cotan_weights(v0, v1, v2); |
| 29 | laplacian.segment(dim*face[0], dim) += cotan_weights[2] * (v0-v1) + cotan_weights[1] * (v0-v2); |
| 30 | laplacian.segment(dim*face[1], dim) += cotan_weights[0] * (v1-v2) + cotan_weights[2] * (v1-v0); |
| 31 | laplacian.segment(dim*face[2], dim) += cotan_weights[1] * (v2-v0) + cotan_weights[0] * (v2-v1); |
| 32 | } |
| 33 | } |
| 34 | |
| 35 | VectorF VertexLaplacianAttribute::compute_cotan_weights( |
| 36 | const VectorF& v0, const VectorF& v1, const VectorF& v2) { |
nothing calls this directly
no test coverage detected