diff --git a/src/smoothing.cpp b/src/smoothing.cpp index 01a7f02..fccdd79 100644 --- a/src/smoothing.cpp +++ b/src/smoothing.cpp @@ -10,27 +10,30 @@ /* - vα/--\ - / ------\ vi - / ---X - / /---- / \ - / /--- / -\ - / /---- / \ - vj --- | \ - \-- / -\ - \- / /--\ - \-- / /------- - \-+--- + vα/--\ + / ------\ vi + / ---X + / /---- / \ + / /--- / -\ + / /---- / \ + vj --- | \ + \-- / -\ + \- / /--\ + \-- / /------- + \-+--- vβ */ +/* Poids pour le laplacien uniforme, constant à 1. */ double uniform_weight(MyMesh &mesh, HalfedgeHandle vi_vj) { (void) mesh; (void) vi_vj; return 1; } + +/* Masse pour le laplacien uniforme, 1 / taille(N1(vi)). */ double uniform_mass(MyMesh &mesh, VertexHandle vi) { double count = 0; for (VertexHandle v : mesh.vv_range(vi)) { @@ -43,6 +46,7 @@ double uniform_mass(MyMesh &mesh, VertexHandle vi) { /* Calcule le poids cotangent pour l'arête reliant vi à vj. */ double cotangent_weight(MyMesh &mesh, HalfedgeHandle vi_vj) { + // Voir le graphique en haut de ce fichier. Point pj = mesh.point(mesh.to_vertex_handle(vi_vj)); HalfedgeHandle vj_vb = mesh.next_halfedge_handle(vi_vj); Point pb = mesh.point(mesh.to_vertex_handle(vj_vb)); @@ -82,12 +86,15 @@ double barycentric_vertex_area(MyMesh &mesh, VertexHandle vert) { } +/* Fonction de masse pour le laplacien cotangent. */ double cotangent_mass(MyMesh &mesh, VertexHandle vi) { double area = barycentric_vertex_area(mesh, vi); return 1. / (2 * area); } +/* Calcule la matrice laplacienne avec les fonctions de poids d'arête + * et de masse de sommet spécifiées par l'utilisatrice. */ Eigen::SparseMatrix laplacian_matrix(MyMesh &mesh, double (*edge_weight)(MyMesh &, HalfedgeHandle), double (*vertex_mass)(MyMesh &, VertexHandle)) { compute_face_areas(mesh); size_t n_verts = mesh.n_vertices(); @@ -97,19 +104,24 @@ Eigen::SparseMatrix laplacian_matrix(MyMesh &mesh, double (*edge_weight)( if (mesh.is_boundary(vi)) continue; double sum = 0; for (HalfedgeHandle vi_vj : mesh.voh_range(vi)) { + // For each outgoing halfedge VertexHandle vj = mesh.to_vertex_handle(vi_vj); double halfedge_weight = edge_weight(mesh, vi_vj); weight.insert(vi.idx(), vj.idx()) = halfedge_weight; sum -= halfedge_weight; } + // weight(i, i) = -Σ(j in N1(i)) weight(i, j) weight.insert(vi.idx(), vi.idx()) = sum; + mass.insert(vi.idx(), vi.idx()) = vertex_mass(mesh, vi); } return mass * weight; } +/* Adoucissement du maillage. */ void smooth(MyMesh &mesh, SmoothingMethod method, double cotan_factor) { + // Calcul de la matrice laplacienne en fonction de la méthode choisie. double factor; Eigen::SparseMatrix laplacian; if (method == SmoothingMethod::COTANGENT) { @@ -119,7 +131,10 @@ void smooth(MyMesh &mesh, SmoothingMethod method, double cotan_factor) { factor = 1; laplacian = laplacian_matrix(mesh, uniform_weight, uniform_mass); } - // laplacian = laplacian * laplacian; + + laplacian = laplacian * laplacian; // Mise au carré. + + // Transfert des coordonées de chaque point dans une matrice. size_t n_verts = mesh.n_vertices(); Eigen::VectorX X(n_verts), Y(n_verts), Z(n_verts); for (VertexHandle vert : mesh.vertices()) { @@ -130,9 +145,13 @@ void smooth(MyMesh &mesh, SmoothingMethod method, double cotan_factor) { Y(id) = p[1]; Z(id) = p[2]; } + + // Application du laplacien pour calculer les décalages. X = laplacian * X; Y = laplacian * Y; Z = laplacian * Z; + + // Application des décalages. for (VertexHandle vert : mesh.vertices()) { if (mesh.is_boundary(vert)) continue; size_t id = vert.idx();