From 00cc96f96833d5dfcec7003ce76183a3155e793b Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 29 May 2015 09:47:01 +0200 Subject: [PATCH] add code to protect_constraints edges tagged as constraints are not refined when protect_constraints is true --- .../internal/named_function_params.h | 15 ++++ .../internal/remesh_impl.h | 90 ++++++++++++++----- .../CGAL/Polygon_mesh_processing/remesh.h | 6 +- 3 files changed, 90 insertions(+), 21 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/named_function_params.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/named_function_params.h index c2a018f96c3..5bbb17e36dc 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/named_function_params.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/named_function_params.h @@ -35,6 +35,7 @@ namespace CGAL{ enum less_halfedge_t { less_halfedge }; enum geom_traits_t { geom_traits }; enum number_of_iterations_t { number_of_iterations }; + enum protect_constraints_t { protect_constraints }; //internal enum weight_calculator_t { weight_calculator }; @@ -130,6 +131,13 @@ namespace CGAL{ return Params(n, *this); } + pmp_bgl_named_params + protect_constraints(const bool& b) const + { + typedef pmp_bgl_named_params Params; + return Params(b, *this); + } + //overload template pmp_bgl_named_params @@ -252,6 +260,13 @@ namespace parameters{ return Params(n); } + pmp_bgl_named_params + protect_constraints(const bool& b) + { + typedef pmp_bgl_named_params Params; + return Params(b); + } + //overload template pmp_bgl_named_params diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/remesh_impl.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/remesh_impl.h index fd1b37f9161..273c732f9a0 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/remesh_impl.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/remesh_impl.h @@ -96,12 +96,14 @@ namespace internal { Incremental_remesher(PolygonMesh& pmesh , const FaceRange& face_range , VertexPointMap& vpmap - , const EdgeIsConstrainedMap& ecmap) + , const EdgeIsConstrainedMap& ecmap + , const bool protect_constraints) : mesh_(pmesh) , vpmap_(vpmap) , own_tree_(true) , input_triangles_() , halfedge_status_map_() + , protect_constraints_(protect_constraints) { CGAL_assertion(CGAL::is_triangle_mesh(mesh_)); @@ -162,9 +164,12 @@ namespace internal { halfedge_descriptor he = eit->second; double sqlen = eit->first; long_edges.right.erase(eit); - Point refinement_point = this->midpoint(he); + + if (protect_constraints_ && !is_split_allowed(edge(he, mesh_))) + continue; //split edge + Point refinement_point = this->midpoint(he); halfedge_descriptor hnew = CGAL::Euler::split_edge(he, mesh_); CGAL_assertion(he == next(hnew, mesh_)); ++nb_splits; @@ -173,6 +178,11 @@ namespace internal { vertex_descriptor vnew = target(hnew, mesh_); put(vpmap_, vnew, refinement_point); + //after splitting + halfedge_descriptor hnew_opp = opposite(hnew, mesh_); + halfedge_added(hnew, status(he)); + halfedge_added(hnew_opp, status(opposite(he, mesh_))); + //check sub-edges double sqlen_new = 0.25 * sqlen; if (sqlen_new > sq_high) @@ -182,20 +192,13 @@ namespace internal { long_edges.insert(long_edge(next(hnew, mesh_), sqlen_new)); } - //after splitting - halfedge_descriptor hnew_opp = opposite(hnew, mesh_); - halfedge_added(hnew, status(he)); - halfedge_added(hnew_opp, status(opposite(he, mesh_))); - //insert new edges to keep triangular faces, and update long_edges - if (!is_on_border(hnew)) { halfedge_descriptor hnew2 = CGAL::Euler::split_face(hnew, next(next(hnew, mesh_), mesh_), mesh_); - Halfedge_status snew = (is_on_patch(hnew) - || (is_on_patch_border(hnew) && !is_on_patch(hnew_opp))) + Halfedge_status snew = (is_on_patch(hnew) || is_on_patch_border(hnew)) ? PATCH : MESH; halfedge_added(hnew2, snew); @@ -215,8 +218,7 @@ namespace internal { halfedge_descriptor hnew2 = CGAL::Euler::split_face(prev(hnew_opp, mesh_), next(hnew_opp, mesh_), mesh_); - Halfedge_status snew = (is_on_patch(hnew_opp) - || (is_on_patch_border(hnew_opp) && !is_on_patch(hnew))) + Halfedge_status snew = (is_on_patch(hnew_opp) || is_on_patch_border(hnew_opp)) ? PATCH : MESH; halfedge_added(hnew2, snew); @@ -641,23 +643,59 @@ namespace internal { && (plane1.oriented_side(p4) != plane2.oriented_side(p4)); } - //todo : simplify the list of cases bool is_split_allowed(const edge_descriptor& e) const { halfedge_descriptor he = halfedge(e, mesh_); - return is_on_patch(he) //opp is also on patch - || (is_on_border(he) && is_on_patch_border(opposite(he, mesh_))) - || (is_on_border(opposite(he, mesh_)) && is_on_patch_border(he)) - || is_on_patch_border(he) - || is_on_patch_border(opposite(he, mesh_)); + halfedge_descriptor hopp = opposite(he, mesh_); + + bool splittable = false; + if (is_on_patch(face(he, mesh_))) + splittable = is_split_allowed(he); + + if (splittable && is_on_patch(face(hopp, mesh_))) + splittable = is_split_allowed(hopp); + + return splittable; + } + + bool is_split_allowed(const halfedge_descriptor& h) const + { + if (!protect_constraints_)//allow splitting constraints + { + return is_on_patch_border(h) + || is_on_patch(h) + || is_on_border(h); + } + else + { + if (!is_on_patch(h)) //PATCH are the only splittable edges + return false; + else + return is_longest_edge_of_face(h); + } + } + + bool is_longest_edge_of_face(const halfedge_descriptor& h) const + { + double sqh = sqlength(h); + return sqh >= sqlength(next(h, mesh_)) + && sqh >= sqlength(next(next(h, mesh_), mesh_)); } bool is_collapse_allowed(const edge_descriptor& e) const { halfedge_descriptor he = halfedge(e, mesh_); + halfedge_descriptor hopp = opposite(he, mesh_); + + if (protect_constraints_) + { + if (is_on_patch_border(he) || is_on_patch_border(hopp)) + return false; + } + return is_on_patch(he) //opp is also on patch - || (is_on_border(he) && is_on_patch_border(opposite(he, mesh_))) - || (is_on_border(opposite(he, mesh_)) && is_on_patch_border(he)); + || (is_on_border(he) && is_on_patch_border(hopp)) + || (is_on_border(hopp) && is_on_patch_border(he)); } void tag_halfedges_status(const FaceRange& face_range @@ -743,6 +781,17 @@ namespace internal { return res; } + bool is_on_patch(const face_descriptor& f) const + { + BOOST_FOREACH(halfedge_descriptor h, + halfedges_around_face(halfedge(f, mesh_), mesh_)) + { + if (is_on_patch(h) || is_on_patch_border(h)) + return true; + } + return false; + } + bool is_on_patch(const vertex_descriptor& v) const { BOOST_FOREACH(halfedge_descriptor h, @@ -894,6 +943,7 @@ namespace internal { bool own_tree_; Triangle_list input_triangles_; std::map halfedge_status_map_; + bool protect_constraints_; };//end class Incremental_remesher }//end namespace internal diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remesh.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remesh.h index 77667421dbe..ec222d5fba5 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remesh.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remesh.h @@ -71,6 +71,8 @@ void incremental_triangle_based_remeshing(PolygonMesh& pmesh , const double& target_edge_length , const NamedParameters& np) { + std::cout.precision(18); + typedef PolygonMesh PM; using boost::choose_pmap; using boost::get_param; @@ -92,8 +94,10 @@ void incremental_triangle_based_remeshing(PolygonMesh& pmesh = choose_param(get_param(np, edge_is_constrained), internal::Border_constraint_pmap(pmesh, faces)); + bool protect = choose_param(get_param(np, protect_constraints), false); + typename internal::Incremental_remesher - remesher(pmesh, faces, vpmap, ecmap); + remesher(pmesh, faces, vpmap, ecmap, protect); unsigned int nb_iterations = choose_param(get_param(np, number_of_iterations), 1);