void MeshDenoisingViaL0Minimization::solveVertices(TriMesh &mesh, Eigen::MatrixXd &initial_vertices_matrix, std::vector< std::vector<TriMesh::VertexHandle> > &edge_vertex_handle, std::vector< std::vector<double> > &coef, std::vector<TriMesh::Point> &delta, double alpha, double beta) { Eigen::MatrixXd right_term = initial_vertices_matrix; Eigen::SparseMatrix<double> coef_matrix((int)mesh.n_vertices(), (int)mesh.n_vertices()); std::vector< Eigen::Triplet<double> > triple; triple.clear(); std::map<TriMesh::VertexHandle, double> vertex_coef; std::set<TriMesh::EdgeHandle> edge_handle;; for(TriMesh::VertexIter v_it = mesh.vertices_begin(); v_it != mesh.vertices_end(); v_it++) { edge_handle.clear(); vertex_coef.clear(); vertex_coef[*v_it] = 1.0; for(TriMesh::VertexFaceIter vf_it = mesh.vf_iter(*v_it); vf_it.is_valid(); vf_it++) { for(TriMesh::FaceEdgeIter fe_it = mesh.fe_iter(*vf_it); fe_it.is_valid(); fe_it++) { edge_handle.insert(*fe_it); } } TriMesh::Point right(0.0, 0.0, 0.0); for(std::set<TriMesh::EdgeHandle>::iterator s_it = edge_handle.begin(); s_it != edge_handle.end(); s_it++) { if(!mesh.is_boundary(*s_it)) { int index = (*s_it).idx(); TriMesh::VertexHandle v1 = edge_vertex_handle[index][0], v2 = edge_vertex_handle[index][1], v3 = edge_vertex_handle[index][2], v4 = edge_vertex_handle[index][3]; double coe1 = coef[index][0], coe2 = coef[index][1], coe3 = coef[index][2], coe4 = coef[index][3]; TriMesh::Point temp_delta = delta[index]; if(v1 == *v_it) { vertex_coef[v1] = vertex_coef[v1] + alpha + beta * coe1 * coe1; vertex_coef[v2] = vertex_coef[v2] - alpha + beta * coe1 * coe2; vertex_coef[v3] = vertex_coef[v3] + alpha + beta * coe1 * coe3; vertex_coef[v4] = vertex_coef[v4] - alpha + beta * coe1 * coe4; right += temp_delta * beta * coe1; } else if(v2 == *v_it) { vertex_coef[v1] = vertex_coef[v1] - alpha + beta * coe2 * coe1; vertex_coef[v2] = vertex_coef[v2] + alpha + beta * coe2 * coe2; vertex_coef[v3] = vertex_coef[v3] - alpha + beta * coe2 * coe3; vertex_coef[v4] = vertex_coef[v4] + alpha + beta * coe2 * coe4; right += temp_delta * beta * coe2; } else if(v3 == *v_it) { vertex_coef[v1] = vertex_coef[v1] + alpha + beta * coe3 * coe1; vertex_coef[v2] = vertex_coef[v2] - alpha + beta * coe3 * coe2; vertex_coef[v3] = vertex_coef[v3] + alpha + beta * coe3 * coe3; vertex_coef[v4] = vertex_coef[v4] - alpha + beta * coe3 * coe4; right += temp_delta * beta * coe3; } else if(v4 == *v_it) { vertex_coef[v1] = vertex_coef[v1] - alpha + beta * coe4 * coe1; vertex_coef[v2] = vertex_coef[v2] + alpha + beta * coe4 * coe2; vertex_coef[v3] = vertex_coef[v3] - alpha + beta * coe4 * coe3; vertex_coef[v4] = vertex_coef[v4] + alpha + beta * coe4 * coe4; right += temp_delta * beta * coe4; } } } right_term(v_it->idx(), 0) += right[0]; right_term(v_it->idx(), 1) += right[1]; right_term(v_it->idx(), 2) += right[2]; for(std::map<TriMesh::VertexHandle, double>::iterator m_it = vertex_coef.begin(); m_it != vertex_coef.end(); m_it++) { triple.push_back(Eigen::Triplet<double>(v_it->idx(), m_it->first.idx(), m_it->second)); } } coef_matrix.setFromTriplets(triple.begin(), triple.end()); Eigen::SparseLU<Eigen::SparseMatrix<double> > solver; solver.analyzePattern(coef_matrix); solver.factorize(coef_matrix); Eigen::MatrixXd vertices_term = solver.solve(right_term); for(TriMesh::VertexIter v_it = mesh.vertices_begin(); v_it != mesh.vertices_end(); v_it++) { int index = v_it->idx(); TriMesh::Point pt = TriMesh::Point(vertices_term(index,0), vertices_term(index,1), vertices_term(index,2)); mesh.set_point(*v_it, pt); } }