#include "quad_patch_tesselator.h" #include "mesh_processor.h" #include "util.h" #include "hole_filling.h" #include "smoothing.h" #include "curvature.h" #include #include MeshProcessor::MeshProcessor(const QString &path, MeshViewer &mesh_viewer, double implicit_hole_filling_scale, double implicit_hole_filling_discr) :mesh_viewer(mesh_viewer), implicit_hole_filling_scale(implicit_hole_filling_scale), implicit_hole_filling_discr(implicit_hole_filling_discr) { OpenMesh::IO::Options options; options.set(OpenMesh::IO::Options::VertexColor); if (!OpenMesh::IO::read_mesh(mesh, path.toUtf8().constData(), options)) { qWarning() << "Failed to read" << path; return; } for (VertexHandle vh : mesh.vertices()) { mesh.set_color(vh, MyMesh::Color(.5, .5, .5)); } courbure = new Courbures(mesh); try { courbure->compute_KH(); courbure->set_K_colors(); } catch (std::runtime_error &e) { qWarning() << "Curvature computation failed"; } connect(&mesh_viewer, &MeshViewer::clicked, this, &MeshProcessor::click); updateView(); } MeshProcessor::~MeshProcessor() { if (mesh_viewer.isInitialized()) { mesh_viewer.removeMesh(mesh); } if (courbure) delete courbure; } void MeshProcessor::updateView() const { if (mesh_viewer.isInitialized()) { mesh_viewer.removeMesh(mesh); mesh_viewer.addMesh(mesh); mesh_viewer.updateForReal(); } else { connect(&mesh_viewer, &MeshViewer::initialized, [&]() { mesh_viewer.addMesh(mesh); mesh_viewer.updateForReal(); }); } } void MeshProcessor::fillHolesDumb() { ::fillHolesDumb(mesh); updateView(); } void MeshProcessor::fillHolesImplicit() { for (MyMesh &filling : fillings) { mesh_viewer.removeMesh(filling); } std::vector new_fillings = ::fillHolesImplicit(mesh, implicit_hole_filling_scale, implicit_hole_filling_discr); for (MyMesh &filling : new_fillings) { fillings.push_back(filling); mesh_viewer.addMesh(fillings[fillings.size() - 1]); } updateView(); } void MeshProcessor::setImplicitHoleFillingScale(float scale) { implicit_hole_filling_scale = scale; if (fillings.size() > 0) { fillHolesImplicit(); } } void MeshProcessor::setImplicitHoleFillingDiscr(float discr) { implicit_hole_filling_discr = discr; if (fillings.size() > 0) { fillHolesImplicit(); } } void MeshProcessor::smoothCotangent(double factor) { ::smooth(mesh, SmoothingMethod::COTANGENT, factor); updateView(); } void MeshProcessor::smoothUniform() { ::smooth(mesh, SmoothingMethod::UNIFORM); updateView(); } void MeshProcessor::setPatchView(bool on) { view_patches = on; } void MeshProcessor::click(QVector3D position) { if (!view_patches) return; Eigen::Vector3d pos {position.x(), position.y(), position.z()}; MyMesh::VertexIter it = mesh.vertices_begin(); VertexHandle min_vert = *it; double min_dist = (mesh.point(*it) - pos).squaredNorm(); for (; it != mesh.vertices_end(); ++it) { double dist = (mesh.point(*it) - pos).squaredNorm(); if (dist < min_dist) { min_dist = dist; min_vert = *it; } } QuadPatch q = mesh.property(courbure->vprop_quad, min_vert); patch = tesselate_quad_patch(q, mesh, min_vert); mesh_viewer.removeMesh(patch); mesh_viewer.addMesh(patch); mesh_viewer.updateForReal(); }