111 lines
4.1 KiB
C++
111 lines
4.1 KiB
C++
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
|
#include <CGAL/Surface_mesh.h>
|
|
#include <CGAL/boost/graph/graph_traits_Surface_mesh.h>
|
|
#include <CGAL/Polygon_mesh_processing/remesh.h>
|
|
#include <CGAL/Polygon_mesh_processing/border.h>
|
|
#include <CGAL/Polygon_mesh_processing/repair.h>
|
|
#include <CGAL/Polygon_mesh_processing/triangulate_faces.h>
|
|
#include <boost/function_output_iterator.hpp>
|
|
#include "remeshhole.h"
|
|
|
|
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
|
typedef Kernel::Point_3 Point;
|
|
typedef CGAL::Surface_mesh<Kernel::Point_3> Mesh;
|
|
typedef boost::graph_traits<Mesh>::halfedge_descriptor halfedge_descriptor;
|
|
typedef boost::graph_traits<Mesh>::edge_descriptor edge_descriptor;
|
|
typedef boost::graph_traits<Mesh>::vertex_iterator vertex_iterator;
|
|
typedef boost::graph_traits<Mesh>::vertex_descriptor vertex_descriptor;
|
|
|
|
struct halfedge2edge
|
|
{
|
|
halfedge2edge(const Mesh& m, std::vector<edge_descriptor>& edges)
|
|
: m_mesh(m), m_edges(edges)
|
|
{}
|
|
void operator()(const halfedge_descriptor& h) const
|
|
{
|
|
m_edges.push_back(edge(h, m_mesh));
|
|
}
|
|
const Mesh& m_mesh;
|
|
std::vector<edge_descriptor>& m_edges;
|
|
};
|
|
|
|
void remeshHole(std::vector<QVector3D> &vertices,
|
|
const std::vector<size_t> &hole,
|
|
std::vector<std::vector<size_t>> &newFaces)
|
|
{
|
|
if (hole.empty())
|
|
return;
|
|
|
|
Mesh mesh;
|
|
|
|
double targetEdgeLength = 0;
|
|
for (size_t i = 0; i < hole.size(); ++i) {
|
|
size_t j = (i + 1) % hole.size();
|
|
targetEdgeLength += (vertices[hole[i]] - vertices[hole[j]]).length();
|
|
}
|
|
targetEdgeLength /= hole.size();
|
|
targetEdgeLength *= 1.2;
|
|
|
|
std::vector<typename CGAL::Surface_mesh<typename Kernel::Point_3>::Vertex_index> meshFace;
|
|
std::vector<size_t> originalIndices;
|
|
originalIndices.reserve(hole.size());
|
|
for (const auto &v: hole) {
|
|
originalIndices.push_back(v);
|
|
const auto &position = vertices[v];
|
|
meshFace.push_back(mesh.add_vertex(Point(position.x(), position.y(), position.z())));
|
|
}
|
|
mesh.add_face(meshFace);
|
|
|
|
std::vector<edge_descriptor> border;
|
|
|
|
CGAL::Polygon_mesh_processing::triangulate_faces(mesh);
|
|
|
|
CGAL::Polygon_mesh_processing::border_halfedges(faces(mesh),
|
|
mesh,
|
|
boost::make_function_output_iterator(halfedge2edge(mesh, border)));
|
|
|
|
auto ecm = mesh.add_property_map<edge_descriptor, bool>("ecm").first;
|
|
for (edge_descriptor e: border)
|
|
ecm[e] = true;
|
|
|
|
Mesh::Property_map<Mesh::Vertex_index, size_t> meshPropertyMap;
|
|
bool created;
|
|
boost::tie(meshPropertyMap, created) = mesh.add_property_map<Mesh::Vertex_index, size_t>("v:source", 0);
|
|
|
|
size_t vertexIndex = 0;
|
|
for (auto vertexIt = mesh.vertices_begin(); vertexIt != mesh.vertices_end(); vertexIt++) {
|
|
meshPropertyMap[*vertexIt] = originalIndices[vertexIndex++];
|
|
}
|
|
|
|
unsigned int nb_iter = 3;
|
|
|
|
CGAL::Polygon_mesh_processing::isotropic_remeshing(faces(mesh),
|
|
targetEdgeLength,
|
|
mesh,
|
|
CGAL::Polygon_mesh_processing::parameters::number_of_iterations(nb_iter)
|
|
.protect_constraints(true)
|
|
.edge_is_constrained_map(ecm));
|
|
|
|
for (auto vertexIt = mesh.vertices_begin() + vertexIndex; vertexIt != mesh.vertices_end(); vertexIt++) {
|
|
auto point = mesh.point(*vertexIt);
|
|
originalIndices.push_back(vertices.size());
|
|
vertices.push_back(QVector3D(
|
|
CGAL::to_double(point.x()),
|
|
CGAL::to_double(point.y()),
|
|
CGAL::to_double(point.z())
|
|
));
|
|
meshPropertyMap[*vertexIt] = originalIndices[vertexIndex++];
|
|
}
|
|
|
|
for (const auto &faceIt: mesh.faces()) {
|
|
CGAL::Vertex_around_face_iterator<Mesh> vbegin, vend;
|
|
std::vector<size_t> faceIndices;
|
|
for (boost::tie(vbegin, vend) = CGAL::vertices_around_face(mesh.halfedge(faceIt), mesh);
|
|
vbegin != vend;
|
|
++vbegin) {
|
|
faceIndices.push_back(meshPropertyMap[*vbegin]);
|
|
}
|
|
newFaces.push_back(faceIndices);
|
|
}
|
|
}
|