add an option to refuse a repair that is too far from the input

using Polyhedral_envelope
This commit is contained in:
Sébastien Loriot 2020-12-03 10:43:03 +01:00
parent 8d45889b6a
commit 5f6dca4738
1 changed files with 109 additions and 8 deletions

View File

@ -22,6 +22,9 @@
#include <CGAL/Polygon_mesh_processing/self_intersections.h>
#include <CGAL/Polygon_mesh_processing/smooth_mesh.h>
#include <CGAL/Polygon_mesh_processing/triangulate_hole.h>
#ifndef CGAL_PMP_REMOVE_SELF_INTERSECTION_NO_POLYHEDRAL_ENVELOPE_CHECK
#include <CGAL/Polyhedral_envelope.h>
#endif
#include <CGAL/assertions.h>
#include <CGAL/boost/graph/copy_face_graph.h>
@ -44,6 +47,7 @@
// #define CGAL_PMP_REMOVE_SELF_INTERSECTIONS_NO_SMOOTHING
// #define CGAL_PMP_REMOVE_SELF_INTERSECTIONS_NO_CONSTRAINTS_IN_HOLE_FILLING
// #define CGAL_PMP_REMOVE_SELF_INTERSECTION_NO_POLYHEDRAL_ENVELOPE_CHECK
// Self-intersection removal is done by making a big-enough hole and filling it
//
@ -440,6 +444,9 @@ bool remove_self_intersections_with_smoothing(std::set<typename boost::graph_tra
const bool constrain_sharp_edges,
const double dihedral_angle,
const double weak_DA,
#ifndef CGAL_PMP_REMOVE_SELF_INTERSECTION_NO_POLYHEDRAL_ENVELOPE_CHECK
const Polyhedral_envelope<GeomTraits>& cc_envelope,
#endif
VertexPointMap vpm,
const GeomTraits& gt)
{
@ -490,7 +497,21 @@ bool remove_self_intersections_with_smoothing(std::set<typename boost::graph_tra
#endif
if(does_self_intersect(local_mesh))
{
#ifdef CGAL_PMP_REMOVE_SELF_INTERSECTION_DEBUG
std::cout << " DEBUG: patch still self-intersecting after smoothing\n";
#endif
return false;
}
#ifndef CGAL_PMP_REMOVE_SELF_INTERSECTION_NO_POLYHEDRAL_ENVELOPE_CHECK
if (!cc_envelope.empty() && !cc_envelope(local_mesh))
{
#ifdef CGAL_PMP_REMOVE_SELF_INTERSECTION_DEBUG
std::cout << " DEBUG: patch is not in the input polyhedral envelope\n";
#endif
return false;
}
#endif
std::vector<std::vector<Point> > patch;
for(const face_descriptor f : faces(local_mesh))
@ -1031,6 +1052,9 @@ bool fill_hole(std::vector<typename boost::graph_traits<TriangleMesh>::halfedge_
std::set<typename boost::graph_traits<TriangleMesh>::face_descriptor>& cc_faces,
std::set<typename boost::graph_traits<TriangleMesh>::face_descriptor>& working_face_range,
TriangleMesh& tmesh,
#ifndef CGAL_PMP_REMOVE_SELF_INTERSECTION_NO_POLYHEDRAL_ENVELOPE_CHECK
const CGAL::Polyhedral_envelope<GeomTraits>& cc_envelope,
#endif
VertexPointMap vpm,
const GeomTraits& gt)
{
@ -1068,6 +1092,16 @@ bool fill_hole(std::vector<typename boost::graph_traits<TriangleMesh>::halfedge_
return false;
}
#ifndef CGAL_PMP_REMOVE_SELF_INTERSECTION_NO_POLYHEDRAL_ENVELOPE_CHECK
if (!cc_envelope.empty() && !cc_envelope(patch))
{
#ifdef CGAL_PMP_REMOVE_SELF_INTERSECTION_DEBUG
std::cout << " DEBUG: Patch is not inside the input polyhedral envelope\n";
#endif
return false;
}
#endif
// Could renew the range directly within the patch replacement function
// to avoid erasing and re-adding the same face
for(const face_descriptor f : cc_faces)
@ -1096,6 +1130,9 @@ template <typename TriangleMesh, typename VertexPointMap, typename GeomTraits>
bool fill_hole(std::set<typename boost::graph_traits<TriangleMesh>::face_descriptor>& cc_faces,
std::set<typename boost::graph_traits<TriangleMesh>::face_descriptor>& working_face_range,
TriangleMesh& tmesh,
#ifndef CGAL_PMP_REMOVE_SELF_INTERSECTION_NO_POLYHEDRAL_ENVELOPE_CHECK
const CGAL::Polyhedral_envelope<GeomTraits>& cc_envelope,
#endif
VertexPointMap vpm,
const GeomTraits& gt)
{
@ -1116,7 +1153,11 @@ bool fill_hole(std::set<typename boost::graph_traits<TriangleMesh>::face_descrip
}
if(order_border_halfedge_range(cc_border_hedges, tmesh))
return fill_hole(cc_border_hedges, cc_faces, working_face_range, tmesh, vpm, gt);
return fill_hole(cc_border_hedges, cc_faces, working_face_range, tmesh,
#ifndef CGAL_PMP_REMOVE_SELF_INTERSECTION_NO_POLYHEDRAL_ENVELOPE_CHECK
cc_envelope,
#endif
vpm, gt);
else
return false;
}
@ -1128,6 +1169,9 @@ bool fill_hole_with_constraints(std::vector<typename boost::graph_traits<Triangl
TriangleMesh& tmesh,
const double dihedral_angle,
const double weak_DA,
#ifndef CGAL_PMP_REMOVE_SELF_INTERSECTION_NO_POLYHEDRAL_ENVELOPE_CHECK
const CGAL::Polyhedral_envelope<GeomTraits>& cc_envelope,
#endif
VertexPointMap vpm,
const GeomTraits& gt)
{
@ -1175,7 +1219,11 @@ bool fill_hole_with_constraints(std::vector<typename boost::graph_traits<Triangl
if(!construct_tentative_sub_hole_patch(patch, sub_cc, cc_faces, tmesh, vpm, gt))
{
// Something went wrong while finding a potential cover for the a sub-hole --> use basic hole-filling
return fill_hole(cc_border_hedges, cc_faces, working_face_range, tmesh, vpm, gt);
return fill_hole(cc_border_hedges, cc_faces, working_face_range, tmesh,
#ifndef CGAL_PMP_REMOVE_SELF_INTERSECTION_NO_POLYHEDRAL_ENVELOPE_CHECK
cc_envelope,
#endif
vpm, gt);
}
}
#ifdef CGAL_PMP_REMOVE_SELF_INTERSECTION_DEBUG
@ -1209,9 +1257,28 @@ bool fill_hole_with_constraints(std::vector<typename boost::graph_traits<Triangl
#ifdef CGAL_PMP_REMOVE_SELF_INTERSECTION_DEBUG
std::cout << "Unhealthy patch, use base fill_hole" << std::endl;
#endif
return fill_hole(cc_border_hedges, cc_faces, working_face_range, tmesh, vpm, gt);
return fill_hole(cc_border_hedges, cc_faces, working_face_range, tmesh,
#ifndef CGAL_PMP_REMOVE_SELF_INTERSECTION_NO_POLYHEDRAL_ENVELOPE_CHECK
cc_envelope,
#endif
vpm, gt);
}
#ifndef CGAL_PMP_REMOVE_SELF_INTERSECTION_NO_POLYHEDRAL_ENVELOPE_CHECK
// check if the patch is inside the input polyhedral envelope
if(!cc_envelope.empty() && !cc_envelope(patch))
{
#ifdef CGAL_PMP_REMOVE_SELF_INTERSECTION_DEBUG
std::cout << "Patch is not entirely inside the input polyhedral envelope, use base fill_hole" << std::endl;
#endif
return fill_hole(cc_border_hedges, cc_faces, working_face_range, tmesh,
#ifndef CGAL_PMP_REMOVE_SELF_INTERSECTION_NO_POLYHEDRAL_ENVELOPE_CHECK
cc_envelope,
#endif
vpm, gt);
}
#endif
// Plug the hole-filling patch in the mesh
std::set<face_descriptor> new_faces;
replace_faces_with_patch(cc_faces, patch, tmesh, vpm, std::inserter(new_faces, new_faces.end()));
@ -1324,6 +1391,9 @@ bool remove_self_intersections_with_hole_filling(std::vector<typename boost::gra
bool local_self_intersection_removal,
const double strong_dihedral_angle,
const double weak_dihedral_angle,
#ifndef CGAL_PMP_REMOVE_SELF_INTERSECTION_NO_POLYHEDRAL_ENVELOPE_CHECK
const Polyhedral_envelope<GeomTraits>& cc_envelope,
#endif
VertexPointMap vpm,
const GeomTraits& gt)
{
@ -1352,11 +1422,19 @@ bool remove_self_intersections_with_hole_filling(std::vector<typename boost::gra
if(local_self_intersection_removal)
{
success = fill_hole_with_constraints(cc_border_hedges, cc_faces, working_face_range, tmesh,
strong_dihedral_angle, weak_dihedral_angle, vpm, gt);
strong_dihedral_angle, weak_dihedral_angle,
#ifndef CGAL_PMP_REMOVE_SELF_INTERSECTION_NO_POLYHEDRAL_ENVELOPE_CHECK
cc_envelope,
#endif
vpm, gt);
}
else
{
success = fill_hole(cc_border_hedges, cc_faces, working_face_range, tmesh, vpm, gt);
success = fill_hole(cc_border_hedges, cc_faces, working_face_range, tmesh,
#ifndef CGAL_PMP_REMOVE_SELF_INTERSECTION_NO_POLYHEDRAL_ENVELOPE_CHECK
cc_envelope,
#endif
vpm, gt);
}
#ifdef CGAL_PMP_REMOVE_SELF_INTERSECTION_DEBUG
@ -1383,6 +1461,7 @@ remove_self_intersections_one_step(std::set<typename boost::graph_traits<Triangl
const bool only_treat_self_intersections_locally,
const double strong_dihedral_angle,
const double weak_dihedral_angle,
const double containment_epsilon,
VertexPointMap vpm,
const GeomTraits& gt)
{
@ -1646,6 +1725,14 @@ remove_self_intersections_one_step(std::set<typename boost::graph_traits<Triangl
// Now, we have a proper selection that we can work on.
#ifndef CGAL_PMP_REMOVE_SELF_INTERSECTION_NO_POLYHEDRAL_ENVELOPE_CHECK
Polyhedral_envelope<GeomTraits> cc_envelope;
if (containment_epsilon!=0)
cc_envelope = Polyhedral_envelope<GeomTraits>(cc_faces, tmesh, containment_epsilon);
#else
CGAL_USE(containment_epsilon);
#endif
#ifndef CGAL_PMP_REMOVE_SELF_INTERSECTIONS_NO_SMOOTHING
// First, try to smooth if we only care about local self-intersections
// Two different approaches:
@ -1664,7 +1751,11 @@ remove_self_intersections_one_step(std::set<typename boost::graph_traits<Triangl
{
fixed_by_smoothing = remove_self_intersections_with_smoothing(cc_faces, tmesh, true,
strong_dihedral_angle,
weak_dihedral_angle, vpm, gt);
weak_dihedral_angle,
#ifndef CGAL_PMP_REMOVE_SELF_INTERSECTION_NO_POLYHEDRAL_ENVELOPE_CHECK
cc_envelope,
#endif
vpm, gt);
if(!fixed_by_smoothing) // try again, but without constraining sharp edges
{
@ -1674,7 +1765,11 @@ remove_self_intersections_one_step(std::set<typename boost::graph_traits<Triangl
fixed_by_smoothing = remove_self_intersections_with_smoothing(cc_faces, tmesh, false,
strong_dihedral_angle,
weak_dihedral_angle, vpm, gt);
weak_dihedral_angle,
#ifndef CGAL_PMP_REMOVE_SELF_INTERSECTION_NO_POLYHEDRAL_ENVELOPE_CHECK
cc_envelope,
#endif
vpm, gt);
}
}
@ -1811,6 +1906,9 @@ remove_self_intersections_one_step(std::set<typename boost::graph_traits<Triangl
if(!remove_self_intersections_with_hole_filling(cc_border_hedges, cc_faces, working_face_range,
tmesh, only_treat_self_intersections_locally,
strong_dihedral_angle, weak_dihedral_angle,
#ifndef CGAL_PMP_REMOVE_SELF_INTERSECTION_NO_POLYHEDRAL_ENVELOPE_CHECK
cc_envelope,
#endif
vpm, gt))
{
#ifdef CGAL_PMP_REMOVE_SELF_INTERSECTION_DEBUG
@ -1881,6 +1979,9 @@ bool remove_self_intersections(const FaceRange& face_range,
// detect_feature_pp NP (unused for now)
const double weak_dihedral_angle = 0.; // choose_parameter(get_parameter(np, internal_np::weak_dihedral_angle), 20.);
// use containment check
const double containment_epsilon = choose_parameter(get_parameter(np, internal_np::polyhedral_envelope_epsilon), 0.);
#ifdef CGAL_PMP_REMOVE_SELF_INTERSECTION_DEBUG
std::cout << "DEBUG: Starting remove_self_intersections, is_valid(tmesh)? " << is_valid_polygon_mesh(tmesh) << "\n";
std::cout << "\tpreserve_genus: " << preserve_genus << std::endl;
@ -1932,7 +2033,7 @@ bool remove_self_intersections(const FaceRange& face_range,
internal::remove_self_intersections_one_step(
faces_to_remove, working_face_range, tmesh,
step, preserve_genus, only_treat_self_intersections_locally,
strong_dihedral_angle, weak_dihedral_angle, vpm, gt);
strong_dihedral_angle, weak_dihedral_angle, containment_epsilon, vpm, gt);
#ifdef CGAL_PMP_REMOVE_SELF_INTERSECTION_DEBUG
if(all_fixed && topology_issue)