diff --git a/BGL/include/CGAL/boost/parameter.h b/BGL/include/CGAL/boost/parameter.h index 6549eba09d9..785a8ab97a5 100644 --- a/BGL/include/CGAL/boost/parameter.h +++ b/BGL/include/CGAL/boost/parameter.h @@ -111,6 +111,7 @@ BOOST_PARAMETER_NAME( (dump_after_perturb_prefix, tag ) dump_after_perturb_prefi BOOST_PARAMETER_NAME( (dump_after_exude_prefix, tag ) dump_after_exude_prefix_) BOOST_PARAMETER_NAME( (number_of_initial_points, tag) number_of_initial_points_) BOOST_PARAMETER_NAME( (maximal_number_of_vertices, tag ) maximal_number_of_vertices_) +BOOST_PARAMETER_NAME( (nonlinear_growth_of_balls, tag ) nonlinear_growth_of_balls_) BOOST_PARAMETER_NAME( (pointer_to_error_code, tag ) pointer_to_error_code_) BOOST_PARAMETER_NAME( (pointer_to_stop_atomic_boolean, tag ) pointer_to_stop_atomic_boolean_) 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 2f23191b16b..5d26b1f5af8 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 = std::get<0>(*fit); if ( ! is_treated(curve_index) ) { @@ -1148,6 +1197,7 @@ insert_balls(const Vertex_handle& vp, dim, index, out); + if(forced_stop()) return out; const Vertex_handle new_vertex = pair.first; out = pair.second; const FT sn = get_radius(new_vertex); @@ -1277,6 +1327,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 +1347,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 +1394,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 +1409,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 +1433,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 +1609,7 @@ check_and_repopulate_edges() // Fix edges while ( !vertices.empty() ) { + if(forced_stop()) break; Vertex_handle v = *vertices.begin(); vertices.erase(vertices.begin()); @@ -1779,6 +1836,7 @@ walk_along_edge(const Vertex_handle& start, const Vertex_handle& next, // and current intersects enough while ( ! is_sampling_dense_enough(previous, current, curve_index, orientation) ) { + if(forced_stop()) return out; *out++ = current; // Don't go through corners @@ -1887,6 +1945,7 @@ repopulate(InputIterator begin, InputIterator last, #endif // CGAL_MESH_3_PROTECTION_DEBUG *out++ = *current; c3t3_.triangulation().remove(*current); + if(forced_stop()) return out; } // Repopulate edge diff --git a/Mesh_3/include/CGAL/make_mesh_3.h b/Mesh_3/include/CGAL/make_mesh_3.h index d55ed2075a8..abd460b1468 100644 --- a/Mesh_3/include/CGAL/make_mesh_3.h +++ b/Mesh_3/include/CGAL/make_mesh_3.h @@ -197,13 +197,28 @@ template < typename C3T3, typename MeshDomain, typename MeshCriteria> void init_c3t3_with_features(C3T3& c3t3, const MeshDomain& domain, const MeshCriteria& criteria, - bool nonlinear = false) + bool nonlinear = false, + std::size_t maximal_number_of_vertices = 0, + Mesh_error_code* pointer_to_error_code = 0 +#ifndef CGAL_NO_ATOMIC + , CGAL::cpp11::atomic* pointer_to_stop = 0 +#endif + ) { typedef typename MeshCriteria::Edge_criteria Edge_criteria; 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(), + maximal_number_of_vertices, + pointer_to_error_code +#ifndef CGAL_NO_ATOMIC + , pointer_to_stop +#endif + ); protect_edges.set_nonlinear_growth_of_balls(nonlinear); protect_edges(true); @@ -222,12 +237,21 @@ 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, + mesh_options.maximal_number_of_vertices, + mesh_options.pointer_to_error_code +#ifndef CGAL_NO_ATOMIC + , mesh_options.pointer_to_stop_atomic_boolean +#endif + ); } }; @@ -244,12 +268,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 +281,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 +291,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 +312,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 +335,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 +350,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 +363,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); } }; @@ -438,8 +466,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..c8820c610ed 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 @@ -381,6 +384,7 @@ BOOST_PARAMETER_FUNCTION((internal::Mesh_3_options), mesh_3_options, tag, (dump_after_exude_prefix_, (std::string), "" ) (number_of_initial_points_, (int), -1) (maximal_number_of_vertices_, (std::size_t), 0) + (nonlinear_growth_of_balls_, (bool), false) (pointer_to_error_code_, (Mesh_error_code*), ((Mesh_error_code*)0)) (pointer_to_stop_atomic_boolean_, (internal::Mesh_3_options::Pointer_to_stop_atomic_boolean_t), ((internal::Mesh_3_options::Pointer_to_stop_atomic_boolean_t)0)) ) @@ -395,6 +399,7 @@ BOOST_PARAMETER_FUNCTION((internal::Mesh_3_options), mesh_3_options, tag, options.dump_after_perturb_prefix=dump_after_perturb_prefix_; options.dump_after_exude_prefix=dump_after_exude_prefix_; options.number_of_initial_points=number_of_initial_points_; + options.nonlinear_growth_of_balls = nonlinear_growth_of_balls_; options.maximal_number_of_vertices=maximal_number_of_vertices_; options.pointer_to_error_code=pointer_to_error_code_; #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 d10d458824a..e753f9634ea 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); } }; @@ -257,8 +260,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, diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_function.h b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_function.h index 0408113e335..0188d438c2b 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_function.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_function.h @@ -136,8 +136,8 @@ private: private: boost::any object_to_destroy; C3t3& c3t3_; - Domain* domain_; - Mesh_parameters p_; + Domain* const domain_; + Mesh_parameters const p_; std::atomic stop_; Mesher* mesher_; #ifdef CGAL_MESH_3_MESHER_STATUS_ACTIVATED @@ -237,6 +237,7 @@ Mesh_function:: initialize(const Mesh_criteria& criteria, Mesh_fnt::Domain_tag) // for the other domain types { + namespace p = CGAL::parameters; // Initialization of the mesh, either with the protection of sharp // features, or with the initial points (or both). // If `detect_connected_components==true`, the initialization is @@ -250,7 +251,9 @@ initialize(const Mesh_criteria& criteria, Mesh_fnt::Domain_tag) *domain_, criteria, p_.protect_features, - p_.use_sizing_field_with_aabb_tree); + p::mesh_3_options(p::pointer_to_stop_atomic_boolean = &stop_, + p::nonlinear_growth_of_balls = + p_.use_sizing_field_with_aabb_tree)); } template < typename D_, typename Tag >