145 lines
3.4 KiB
C++
145 lines
3.4 KiB
C++
#include "quad_patch_tesselator.h"
|
|
#include "mesh_processor.h"
|
|
#include "util.h"
|
|
#include "hole_filling.h"
|
|
#include "smoothing.h"
|
|
#include "curvature.h"
|
|
#include "noise_removal.h"
|
|
#include <QGenericMatrix>
|
|
#include <unordered_set>
|
|
|
|
|
|
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() {
|
|
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<MyMesh> 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();
|
|
}
|
|
|
|
|
|
void MeshProcessor::removeNoise(int value) {
|
|
std::cout << value << std::endl;
|
|
::remove_noise(mesh, value);
|
|
mesh_viewer.removeMesh(mesh);
|
|
mesh_viewer.addMesh(mesh);
|
|
mesh_viewer.updateForReal();
|
|
}
|