From a1e3e05558f52c0d9157aeca6836a8517fb18ed4 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 3 May 2019 11:46:13 +0200 Subject: [PATCH] Add maximal_number_of_vertices and stop_ptr to the protection code --- .../CGAL/Mesh_3/Protect_edges_sizing_field.h | 64 +++++++++++++++++-- Mesh_3/include/CGAL/make_mesh_3.h | 54 +++++++++------- Mesh_3/include/CGAL/refine_mesh_3.h | 7 +- .../include/CGAL/make_periodic_3_mesh_3.h | 36 ++++++----- 4 files changed, 116 insertions(+), 45 deletions(-) diff --git a/Mesh_3/include/CGAL/Mesh_3/Protect_edges_sizing_field.h b/Mesh_3/include/CGAL/Mesh_3/Protect_edges_sizing_field.h index b7e7bc2f573..36d57935a4d 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Protect_edges_sizing_field.h +++ b/Mesh_3/include/CGAL/Mesh_3/Protect_edges_sizing_field.h @@ -44,6 +44,7 @@ #include #include #include +#include #if CGAL_MESH_3_PROTECTION_DEBUG # include #endif @@ -55,6 +56,7 @@ #include #include #include +#include #include @@ -148,7 +150,13 @@ public: Protect_edges_sizing_field(C3T3& c3t3, const MeshDomain& domain, SizingFunction size=SizingFunction(), - const FT minimal_size = FT()); + const FT minimal_size = FT(), + std::size_t maximal_number_of_vertices = 0, + Mesh_error_code* error_code = 0 +#ifndef CGAL_NO_ATOMIC + , CGAL::cpp11::atomic* stop_ptr = 0 +#endif + ); void operator()(const bool refine = true); @@ -156,6 +164,27 @@ public: nonlinear_growth_of_balls = b; } + bool forced_stop() const { +#ifndef CGAL_NO_ATOMIC + if(stop_ptr_ != 0 && + stop_ptr_->load(CGAL::cpp11::memory_order_acquire) == true) + { + if(error_code_ != 0) *error_code_ = CGAL_MESH_3_STOPPED; + return true; + } +#endif // not defined CGAL_NO_ATOMIC + if(maximal_number_of_vertices_ != 0 && + c3t3_.triangulation().number_of_vertices() >= + maximal_number_of_vertices_) + { + if(error_code_ != 0) { + *error_code_ = CGAL_MESH_3_MAXIMAL_NUMBER_OF_VERTICES_REACHED; + } + return true; + } + return false; + } + private: typedef std::vector > Incident_edges; typedef std::vector Vertex_vector; @@ -440,13 +469,25 @@ private: Vertex_set unchecked_vertices_; int refine_balls_iteration_nb; bool nonlinear_growth_of_balls; + std::size_t maximal_number_of_vertices_; + Mesh_error_code* const error_code_; +#ifndef CGAL_NO_ATOMIC + /// Pointer to the atomic Boolean that can stop the process + CGAL::cpp11::atomic* const stop_ptr_; +#endif }; template Protect_edges_sizing_field:: Protect_edges_sizing_field(C3T3& c3t3, const MD& domain, - Sf size, const FT minimal_size) + Sf size, const FT minimal_size, + std::size_t maximal_number_of_vertices, + Mesh_error_code* error_code +#ifndef CGAL_NO_ATOMIC + , CGAL::cpp11::atomic* stop_ptr +#endif + ) : c3t3_(c3t3) , domain_(domain) , size_(size) @@ -454,6 +495,11 @@ Protect_edges_sizing_field(C3T3& c3t3, const MD& domain, , minimal_weight_(CGAL::square(minimal_size)) , refine_balls_iteration_nb(0) , nonlinear_growth_of_balls(false) + , maximal_number_of_vertices_(maximal_number_of_vertices) + , error_code_(error_code) +#ifndef CGAL_NO_ATOMIC + , stop_ptr_(stop_ptr) +#endif { #ifndef CGAL_MESH_3_NO_PROTECTION_NON_LINEAR set_nonlinear_growth_of_balls(); @@ -491,7 +537,7 @@ operator()(const bool refine) #endif // Solve problems - if ( refine ) + if ( refine && !forced_stop()) { refine_balls(); #ifdef CGAL_MESH_3_VERBOSE @@ -523,6 +569,7 @@ insert_corners() for ( typename Initial_corners::iterator it = corners.begin(), end = corners.end() ; it != end ; ++it ) { + if(forced_stop()) break; const Bare_point& p = it->second; dt.insert(p); } @@ -530,6 +577,7 @@ insert_corners() for ( typename Initial_corners::iterator cit = corners.begin(), end = corners.end() ; cit != end ; ++cit ) { + if(forced_stop()) break; const Bare_point& p = cit->second; Index p_index = domain_.index_from_corner_index(cit->first); @@ -907,6 +955,7 @@ insert_balls_on_edges() for ( typename Input_features::iterator fit = input_features.begin(), end = input_features.end() ; fit != end ; ++fit ) { + if(forced_stop()) break; const Curve_index& curve_index = CGAL::cpp11::get<0>(*fit); if ( ! is_treated(curve_index) ) { @@ -1277,6 +1326,7 @@ refine_balls() while ( (!unchecked_vertices_.empty() || restart) && this->refine_balls_iteration_nb < refine_balls_max_nb_of_loops) { + if(forced_stop()) break; #ifdef CGAL_MESH_3_DUMP_FEATURES_PROTECTION_ITERATIONS std::ostringstream oss; oss << "dump_protecting_balls_" << refine_balls_iteration_nb << ".cgal"; @@ -1296,6 +1346,7 @@ refine_balls() for(typename Tr::Finite_edges_iterator eit = tr.finite_edges_begin(), end = tr.finite_edges_end(); eit != end; ++eit) { + if(forced_stop()) break; const Vertex_handle& va = eit->first->vertex(eit->second); const Vertex_handle& vb = eit->first->vertex(eit->third); @@ -1342,6 +1393,7 @@ refine_balls() } } } + if(forced_stop()) new_sizes.clear(); // The std::map with Vertex_handle as the key is not robust, because // the time stamp of vertices can change during the following loop. The @@ -1356,6 +1408,7 @@ refine_balls() end = new_sizes_copy.end(); it != end ; ++it ) { + if(forced_stop()) break; const Vertex_handle v = it->first; const FT new_size = it->second; // Set size of the ball to new value @@ -1379,7 +1432,9 @@ refine_balls() dump_c3t3_edges(c3t3_, "dump-before-check_and_repopulate_edges"); #endif // Check edges - check_and_repopulate_edges(); + if(!forced_stop()) { + check_and_repopulate_edges(); + } } if(this->refine_balls_iteration_nb == refine_balls_max_nb_of_loops) @@ -1553,6 +1608,7 @@ check_and_repopulate_edges() // Fix edges while ( !vertices.empty() ) { + if(forced_stop()) break; Vertex_handle v = *vertices.begin(); vertices.erase(vertices.begin()); diff --git a/Mesh_3/include/CGAL/make_mesh_3.h b/Mesh_3/include/CGAL/make_mesh_3.h index 13ca5c07ebc..6b6e9cb3353 100644 --- a/Mesh_3/include/CGAL/make_mesh_3.h +++ b/Mesh_3/include/CGAL/make_mesh_3.h @@ -203,7 +203,11 @@ void init_c3t3_with_features(C3T3& c3t3, typedef Edge_criteria_sizing_field_wrapper Sizing_field; CGAL::Mesh_3::Protect_edges_sizing_field - protect_edges(c3t3, domain, Sizing_field(criteria.edge_criteria_object())); + protect_edges(c3t3, + domain, + Sizing_field(criteria.edge_criteria_object()), + typename Edge_criteria::FT() + ); protect_edges.set_nonlinear_growth_of_balls(nonlinear); protect_edges(true); @@ -222,12 +226,15 @@ struct C3t3_initializer_base // Not calling 'init_c3t3_with_features' directly to leave it as a free function // outside of the C3T3_initializer class - virtual void initialize_features(C3T3& c3t3, - const MeshDomain& domain, - const MeshCriteria& criteria, - bool nonlinear = false) + virtual void + initialize_features(C3T3& c3t3, + const MeshDomain& domain, + const MeshCriteria& criteria, + const parameters::internal::Mesh_3_options& mesh_options) { - return Mesh_3::internal::init_c3t3_with_features(c3t3, domain, criteria, nonlinear); + return Mesh_3::internal::init_c3t3_with_features + (c3t3, domain, criteria, + mesh_options.nonlinear_growth_of_balls); } }; @@ -244,12 +251,12 @@ struct C3t3_initializer { }; template < typename C3T3, typename MD, typename MC, typename HasFeatures > struct C3t3_initializer < C3T3, MD, MC, false, HasFeatures > { + typedef parameters::internal::Mesh_3_options Mesh_3_options; void operator()(C3T3& c3t3, const MD& domain, const MC& criteria, bool with_features, - bool /* nonlinear */= false, - const int nb_initial_points = -1) + Mesh_3_options mesh_options = Mesh_3_options()) { if ( with_features ) { @@ -257,7 +264,8 @@ struct C3t3_initializer < C3T3, MD, MC, false, HasFeatures > << " without features !" << std::endl; } - init_c3t3(c3t3,domain,criteria,nb_initial_points); + init_c3t3(c3t3,domain,criteria, + mesh_options.number_of_initial_points); } }; @@ -266,15 +274,15 @@ struct C3t3_initializer < C3T3, MD, MC, false, HasFeatures > template < typename C3T3, typename MD, typename MC, typename HasFeatures > struct C3t3_initializer < C3T3, MD, MC, true, HasFeatures > { + typedef parameters::internal::Mesh_3_options Mesh_3_options; void operator()(C3T3& c3t3, const MD& domain, const MC& criteria, bool with_features, - bool nonlinear = false, - const int nb_initial_points = -1) + Mesh_3_options mesh_options = Mesh_3_options()) { C3t3_initializer < C3T3, MD, MC, true, typename MD::Has_features >() - (c3t3,domain,criteria,with_features,nonlinear,nb_initial_points); + (c3t3,domain,criteria,with_features,mesh_options); } }; @@ -287,15 +295,15 @@ struct C3t3_initializer < C3T3, MD, MC, true, CGAL::Tag_true > { virtual ~C3t3_initializer() { } + typedef parameters::internal::Mesh_3_options Mesh_3_options; void operator()(C3T3& c3t3, const MD& domain, const MC& criteria, bool with_features, - bool nonlinear = false, - const int nb_initial_points = -1) + Mesh_3_options mesh_options = Mesh_3_options()) { if ( with_features ) { - this->initialize_features(c3t3, domain, criteria, nonlinear); + this->initialize_features(c3t3, domain, criteria,mesh_options); // If c3t3 initialization is not sufficient (may happen if there is only // a planar curve as feature for example), add some surface points @@ -310,10 +318,12 @@ struct C3t3_initializer < C3T3, MD, MC, true, CGAL::Tag_true > } } if(need_more_init) { - init_c3t3(c3t3, domain, criteria, nb_initial_points); + init_c3t3(c3t3, domain, criteria, + mesh_options.number_of_initial_points); } } - else { init_c3t3(c3t3,domain,criteria,nb_initial_points); } + else { init_c3t3(c3t3,domain,criteria, + mesh_options.number_of_initial_points); } } }; @@ -323,12 +333,12 @@ struct C3t3_initializer < C3T3, MD, MC, true, CGAL::Tag_true > template < typename C3T3, typename MD, typename MC > struct C3t3_initializer < C3T3, MD, MC, true, CGAL::Tag_false > { + typedef parameters::internal::Mesh_3_options Mesh_3_options; void operator()(C3T3& c3t3, const MD& domain, const MC& criteria, bool with_features, - bool /* nonlinear */ = false, - const int nb_initial_points = -1) + Mesh_3_options mesh_options = Mesh_3_options()) { if ( with_features ) { @@ -336,7 +346,8 @@ struct C3t3_initializer < C3T3, MD, MC, true, CGAL::Tag_false > << " without features !" << std::endl; } - init_c3t3(c3t3,domain,criteria,nb_initial_points); + init_c3t3(c3t3,domain,criteria, + mesh_options.number_of_initial_points); } }; @@ -500,8 +511,7 @@ void make_mesh_3_impl(C3T3& c3t3, domain, criteria, with_features, - mesh_options.nonlinear_growth_of_balls, - mesh_options.number_of_initial_points); + mesh_options); CGAL_assertion( c3t3.triangulation().dimension() == 3 ); diff --git a/Mesh_3/include/CGAL/refine_mesh_3.h b/Mesh_3/include/CGAL/refine_mesh_3.h index 4f1196af40d..e89715c24d6 100644 --- a/Mesh_3/include/CGAL/refine_mesh_3.h +++ b/Mesh_3/include/CGAL/refine_mesh_3.h @@ -209,7 +209,10 @@ struct Mesh_3_options { #else typedef bool* Pointer_to_stop_atomic_boolean_t; #endif - Mesh_3_options() + Mesh_3_options(bool nonlinear = false) + // This parameter `nonlinear` adds a compatibility with previous + // API of the constructor of `C3t3_initializer`. + // -- Laurent Rineau, 2019/05/03 : dump_after_init_prefix() , dump_after_refine_surface_prefix() , dump_after_refine_prefix() @@ -217,7 +220,7 @@ struct Mesh_3_options { , dump_after_perturb_prefix() , dump_after_exude_prefix() , number_of_initial_points(-1) - , nonlinear_growth_of_balls(false) + , nonlinear_growth_of_balls(nonlinear) , maximal_number_of_vertices(0) , pointer_to_error_code(0) #ifndef CGAL_NO_ATOMIC diff --git a/Periodic_3_mesh_3/include/CGAL/make_periodic_3_mesh_3.h b/Periodic_3_mesh_3/include/CGAL/make_periodic_3_mesh_3.h index 532fd9fca14..ba4abea5cee 100644 --- a/Periodic_3_mesh_3/include/CGAL/make_periodic_3_mesh_3.h +++ b/Periodic_3_mesh_3/include/CGAL/make_periodic_3_mesh_3.h @@ -93,8 +93,7 @@ struct C3t3_initializer_base const MeshDomain& domain, const MeshCriteria& criteria, bool with_features, - bool nonlinear = false, - const int nb_initial_points = -1) + const parameters::internal::Mesh_3_options& mesh_options) { c3t3.triangulation().set_domain(domain.bounding_box()); c3t3.triangulation().insert_dummy_points(); @@ -102,8 +101,7 @@ struct C3t3_initializer_base // Call the basic initialization from c3t3, which handles features and // adds a bunch of points on the surface - Base::operator()(c3t3, domain, criteria, with_features, - nonlinear, nb_initial_points); + Base::operator()(c3t3, domain, criteria, with_features, mesh_options); } }; @@ -119,9 +117,10 @@ struct C3t3_initializer MeshDomainHasHasFeatures, HasFeatures> Base; void operator()(C3T3& c3t3, const MeshDomain& domain, const MeshCriteria& criteria, - bool with_features, bool nonlinear = false, const int nb_initial_points = -1) + bool with_features, + const parameters::internal::Mesh_3_options& mesh_options) { - return Base::operator()(c3t3, domain, criteria, with_features, nonlinear, nb_initial_points); + return Base::operator()(c3t3, domain, criteria, with_features, mesh_options); } }; @@ -133,10 +132,11 @@ template { void operator()(C3T3& c3t3, const MeshDomain& domain, const MeshCriteria& criteria, - bool with_features, bool nonlinear = false, const int nb_initial_points = -1) + bool with_features, + const parameters::internal::Mesh_3_options& mesh_options) { C3t3_initializer() - (c3t3, domain, criteria, with_features, nonlinear, nb_initial_points); + (c3t3, domain, criteria, with_features, mesh_options); } }; @@ -152,18 +152,21 @@ struct C3t3_initializer virtual ~C3t3_initializer() { } // this override will be used when initialize_features() is called, in make_mesh_3.h - virtual void initialize_features(C3T3& c3t3, - const MeshDomain& domain, - const MeshCriteria& criteria, - bool nonlinear = false) + virtual void + initialize_features(C3T3& c3t3, + const MeshDomain& domain, + const MeshCriteria& criteria, + const parameters::internal::Mesh_3_options& mesh_options) { - return Periodic_3_mesh_3::internal::init_c3t3_with_features(c3t3, domain, criteria, nonlinear); + return Periodic_3_mesh_3::internal::init_c3t3_with_features + (c3t3, domain, criteria, mesh_options.nonlinear_growth_of_balls); } void operator()(C3T3& c3t3, const MeshDomain& domain, const MeshCriteria& criteria, - bool with_features, bool nonlinear = false, const int nb_initial_points = -1) + bool with_features, + const parameters::internal::Mesh_3_options& mesh_options) { - return Base::operator()(c3t3, domain, criteria, with_features, nonlinear, nb_initial_points); + return Base::operator()(c3t3, domain, criteria, with_features, mesh_options); } }; @@ -318,8 +321,7 @@ void make_periodic_3_mesh_3_impl(C3T3& c3t3, domain, criteria, with_features, - mesh_options.nonlinear_growth_of_balls, - mesh_options.number_of_initial_points); + mesh_options); // Build mesher and launch refinement process refine_periodic_3_mesh_3(c3t3, domain, criteria,