diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Isotropic_remeshing/remesh_impl.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Isotropic_remeshing/remesh_impl.h index 12d0a273651..f1eeec4c6a4 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Isotropic_remeshing/remesh_impl.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Isotropic_remeshing/remesh_impl.h @@ -853,11 +853,12 @@ namespace internal { mesh_, vpmap_, vcmap_, ecmap_, gt_, cap_threshold, // bound on the angle: above 160 deg => cap 4, // bound on shortest/longest edge above 4 => needle - 0);// collapse length threshold : not needed here + 0,// collapse length threshold : not needed here + 0); // flip triangle height threshold std::array r2 = internal::is_badly_shaped( face(opposite(he, mesh_), mesh_), - mesh_, vpmap_, vcmap_, ecmap_, gt_, cap_threshold, 4, 0); + mesh_, vpmap_, vcmap_, ecmap_, gt_, cap_threshold, 4, 0, 0); const bool badly_shaped = (r1[0] != boost::graph_traits::null_halfedge()//needle || r1[1] != boost::graph_traits::null_halfedge()//cap diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_degeneracies.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_degeneracies.h index 31d8d003124..7edb6fca279 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_degeneracies.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_degeneracies.h @@ -61,7 +61,8 @@ is_badly_shaped(const typename boost::graph_traits::face_descripto const Traits& gt, const double cap_threshold, // angle over 160° ==> cap const double needle_threshold, // longest edge / shortest edge over this ratio ==> needle - const double collapse_length_threshold) // max length of edges allowed to be collapsed + const double collapse_length_threshold, // max length of edges allowed to be collapsed + const double flip_triangle_height_threshold_squared) // max height of triangles allowed to be flipped { namespace PMP = CGAL::Polygon_mesh_processing; @@ -83,8 +84,14 @@ is_badly_shaped(const typename boost::graph_traits::face_descripto } res = PMP::is_cap_triangle_face(f, tmesh, cap_threshold, parameters::vertex_point_map(vpm).geom_traits(gt)); - if(res != null_h && !get(ecm, edge(res, tmesh))) + if( res != null_h && !get(ecm, edge(res, tmesh) ) && + (flip_triangle_height_threshold_squared == 0 || + typename Traits::Compare_squared_distance_3()( get(vpm, target(next(res,tmesh), tmesh)), + typename Traits::Line_3(get(vpm, source(res,tmesh)), get(vpm, target(res,tmesh))), + flip_triangle_height_threshold_squared) != LARGER )) + { return make_array(null_h, res); + } return make_array(null_h, null_h); } @@ -100,13 +107,15 @@ void collect_badly_shaped_triangles(const typename boost::graph_traits cap const double needle_threshold, // longest edge / shortest edge over this ratio ==> needle const double collapse_length_threshold, // max length of edges allowed to be collapsed + const double flip_triangle_height_threshold_squared, // max height squared of triangles that can be flipped HalfedgeContainer& edges_to_collapse, HalfedgeContainer& edges_to_flip) { typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; std::array res = is_badly_shaped(f, tmesh, vpm, vcm, ecm, gt, cap_threshold, - needle_threshold, collapse_length_threshold); + needle_threshold, + collapse_length_threshold, flip_triangle_height_threshold_squared); if(res[0] != boost::graph_traits::null_halfedge()) { @@ -580,6 +589,9 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, typedef typename boost::property_map::type DVCM; DVCM vcm = get(Vertex_property_tag(), tmesh); + const double flip_triangle_height_threshold_squared = + CGAL::square(choose_parameter(get_parameter(np, internal_np::flip_triangle_height_threshold), 0)); + CGAL_precondition(is_valid_polygon_mesh(tmesh)); CGAL_precondition(is_triangle_mesh(tmesh)); @@ -611,7 +623,8 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, for(face_descriptor f : face_range) { internal::collect_badly_shaped_triangles(f, tmesh, vpm, vcm, ecm, gt, - cap_threshold, needle_threshold, collapse_length_threshold, + cap_threshold, needle_threshold, + collapse_length_threshold, flip_triangle_height_threshold_squared, edges_to_collapse, edges_to_flip); } @@ -671,7 +684,7 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, // Verify that the element is still badly shaped const std::array nc = internal::is_badly_shaped(face(h, tmesh), tmesh, vpm, vcm, ecm, gt, - cap_threshold, needle_threshold, collapse_length_threshold); + cap_threshold, needle_threshold, collapse_length_threshold, flip_triangle_height_threshold_squared); if(nc[0] != h) { @@ -757,7 +770,8 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, if(!is_border(hv, tmesh)) { internal::collect_badly_shaped_triangles(face(hv, tmesh), tmesh, vpm, vcm, ecm, gt, - cap_threshold, needle_threshold, collapse_length_threshold, + cap_threshold, needle_threshold, + collapse_length_threshold, flip_triangle_height_threshold_squared, edges_to_collapse, edges_to_flip); } } @@ -806,7 +820,7 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, std::array nc = internal::is_badly_shaped(face(h, tmesh), tmesh, vpm, vcm, ecm, gt, cap_threshold, needle_threshold, - collapse_length_threshold); + collapse_length_threshold, flip_triangle_height_threshold_squared); // Check the triangle is still a cap if(nc[1] != h) { @@ -868,7 +882,8 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, CGAL_assertion(!is_border(h, tmesh)); std::array nc = internal::is_badly_shaped(face(h, tmesh), tmesh, vpm, vcm, ecm, gt, - cap_threshold, needle_threshold, collapse_length_threshold); + cap_threshold, needle_threshold, + collapse_length_threshold, flip_triangle_height_threshold_squared); if(nc[1] != boost::graph_traits::null_halfedge() && nc[1] != h) next_edges_to_flip.insert(nc[1]); diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/shape_predicates.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/shape_predicates.h index e0f87a849ee..3eb3fa892e6 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/shape_predicates.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/shape_predicates.h @@ -503,7 +503,7 @@ struct Is_cap_angle_over_threshold /// \ingroup PMP_predicates_grp /// /// checks whether a triangle face is a cap. -/// A triangle is said to be a cap if one of the its angles is close to `180` degrees. +/// A triangle is said to be a cap if one of its angles is close to `180` degrees. /// /// @tparam TriangleMesh a model of `FaceGraph` /// @tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters" diff --git a/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h b/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h index 0162e1db87a..cfc54c6631c 100644 --- a/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h +++ b/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h @@ -130,6 +130,7 @@ CGAL_add_named_parameter(match_faces_t, match_faces, match_faces) CGAL_add_named_parameter(face_epsilon_map_t, face_epsilon_map, face_epsilon_map) CGAL_add_named_parameter(maximum_number_t, maximum_number, maximum_number) CGAL_add_named_parameter(use_one_sided_hausdorff_t, use_one_sided_hausdorff, use_one_sided_hausdorff) +CGAL_add_named_parameter(flip_triangle_height_threshold_t, flip_triangle_height_threshold, flip_triangle_height_threshold) // List of named parameters that we use in the package 'Surface Mesh Simplification' CGAL_add_named_parameter(get_cost_policy_t, get_cost_policy, get_cost)