#include "hole_filling.h" #include "IO.h" #include "util.h" #include #include static std::vector> findHoles(MyMesh &mesh) { std::vector> holes; std::set ignore; for (HalfedgeHandle it : mesh.halfedges()) { if (mesh.is_boundary(it) && ignore.find(it) == ignore.end()) { holes.emplace_back(); holes.back().push_back(it); ignore.insert(it); for (HalfedgeHandle it2 : HalfedgeLoopRange(mesh, it)) { holes.back().push_back(it2); ignore.insert(it2); } } } return holes; } void fillHoleDumb(MyMesh &mesh, std::vector &hole) { mesh.request_vertex_status(); mesh.request_edge_status(); mesh.request_face_status(); Point center(0, 0, 0); size_t length = 0; for (HalfedgeHandle it : hole) { VertexHandle vert = mesh.to_vertex_handle(it); center += mesh.point(vert); length++; } center /= length; VertexHandle center_handle = mesh.new_vertex_dirty(center); mesh.set_color(center_handle, mesh.default_color); for (HalfedgeHandle it : hole) { mesh.add_face(mesh.from_vertex_handle(it), mesh.to_vertex_handle(it), center_handle); } } void fillHolesDumb(MyMesh &mesh) { mesh.holes = findHoles(mesh); for (auto hole : mesh.holes) { fillHoleDumb(mesh, hole); } } using namespace std ; using namespace MeshReconstruction; /* ************** Implicit RBF ************** */ Implicit_RBF::Implicit_RBF(vector alpha, vector beta, vector center) : _alpha(alpha), _beta(beta), _center(center) { _n = _alpha.size() ; _d = _beta.size() ; if (_center.size() != _n) throw runtime_error("Inconsistent size of alpha and centers in Implicit_RBF constructor."); } // Computation of the value of the implicit surface at point X float Implicit_RBF::val(MyMesh::Point X) const { float res = 0 ; // Computation of the sum of RBF at centers for(int i=0; i<_n; i++) { res += _alpha.at(i) * myphi((X-_center.at(i)).norm()) ; } // Computation of the polynomial part for(int j=0; j<_d; j++) { res += _beta.at(j) * myp(j, X) ; } return res ; } /* ************** Hole Filling ************** */ Hole_Filling::Hole_Filling(MyMesh &mesh, float scale, float discr) : _mesh(mesh), _scale(scale), _discr(discr) { _mesh.add_property(_vprop, "vprop_flag"); cout << "Starting hole filling ..." << endl ; } // ***** Computation of boundary and its neighborhood MyMesh::HalfedgeHandle Hole_Filling::find_boundary_edge() { MyMesh::HalfedgeIter he_it = _mesh.halfedges_begin(); while ( (he_it != _mesh.halfedges_end()) && (!_mesh.is_boundary(*he_it))) { ++he_it ; } if (he_it != _mesh.halfedges_end()) return *he_it ; else throw std::runtime_error("Boundary HE does not exist") ; } vector Hole_Filling::find_boundary(MyMesh::HalfedgeHandle heh) { MyMesh::HalfedgeHandle heh_ini = heh ; vector boundary ; // Follow (and memorize) boundary edges do { boundary.push_back(_mesh.to_vertex_handle(heh)); heh = _mesh.next_halfedge_handle(heh); } while (heh != heh_ini) ; return boundary ; } void Hole_Filling::init_mark_boundary(const vector & bnd) { for (MyMesh::VertexIter v_it = _mesh.vertices_begin() ; v_it != _mesh.vertices_end(); ++v_it) _mesh.property(_vprop, *v_it) = false ; for (int i=0; i Hole_Filling::next_neighbors(const vector & bnd) { // Visit bnd vertices to find and mark next circle vector next_bnd ; for (int i=0; i, vector &> Hole_Filling::compute_approx_mat(vector vlist, double normal_scale) { const int n(vlist.size()), d(10) ; Eigen::MatrixXd & A = *(new Eigen::MatrixXd(3*n+d,3*n+d)) ; Eigen::MatrixXd Phi(3*n,3*n); Eigen::MatrixXd P(3*n,d); Eigen::VectorXd & B = *(new Eigen::VectorXd(3*n+d)); vector & pts_list = *(new vector); //Append vertices to pts_list for (int i=0; i&, vector&> Hole_Filling::solve_approx(const pair &p, int n, int d) { Eigen::MatrixXd & A = p.first ; Eigen::VectorXd & B = p.second ; Eigen::VectorXd res = A.householderQr().solve(B) ; cout << "End of solver" << endl ; cout << "res : " << res.head(10) << endl ; vector & alpha = *(new vector); vector & beta = *(new vector); if (res.size() != (n+d)) { cout << "taille du res : " << res.size() << endl ; throw std::runtime_error("Error in solve_approx") ; } for (int i=0; i &vlist) { for (MyMesh::VertexIter v_it = _mesh.vertices_begin(); v_it != _mesh.vertices_end() ; ++v_it) { _mesh.set_color(*v_it, MyMesh::Color(200, 200, 200)) ; } for(int i=0; i &vlist) { MyMesh::Point minp = _mesh.point(vlist.at(0)), maxp=minp ; for (int i=0; i (mesh, "bounding_box"); } catch (const std::runtime_error &e) { auto mesh_bb = OpenMesh::getOrMakeProperty (mesh, "bounding_box"); std::vector verts; for (VertexHandle vh : mesh.vertices()) { verts.push_back(vh); } *mesh_bb = hf.estimate_BB(verts); } } MyMesh fillHoleImplicit(MyMesh &mesh, Hole_Filling &hf, std::vector &hole) { computeMeshBoundingBox(mesh, hf); Rect3 mesh_bb = *OpenMesh::getProperty(mesh, "bounding_box"); double diag = mesh_bb.size.Norm(); std::vector verts; for (HalfedgeHandle hh : hole) { verts.push_back(mesh.to_vertex_handle(hh)); } auto bb = hf.estimate_BB(verts) ; verts = hf.next_neighbors(verts); auto [system, pts_list] = hf.compute_approx_mat(verts, diag * .1); auto [alpha, beta] = hf.solve_approx(system, pts_list.size(), 10); Implicit_RBF rbf(alpha, beta, pts_list); Mesh filling = hf.poly_n_out(rbf, bb); MyMesh ret; for (const Vec3 &v : filling.vertices) { VertexHandle vh = ret.new_vertex({v.x, v.y, v.z}); ret.set_color(vh, ret.default_color); } for (const Triangle &t : filling.triangles) { ret.add_face(ret.vertex_handle(t[0]), ret.vertex_handle(t[1]), ret.vertex_handle(t[2])); } return ret; } std::vector fillHolesImplicit(MyMesh &mesh, float scale, float discr) { mesh.holes = findHoles(mesh); std::vector fillings; for (auto hole : mesh.holes) { Hole_Filling hf(mesh, scale, discr); fillings.push_back(fillHoleImplicit(mesh, hf, hole)); } return fillings; }