Add maximal_number_of_vertices and stop_ptr to the protection code

This commit is contained in:
Laurent Rineau 2019-05-03 11:46:13 +02:00
parent f34231dab6
commit a1e3e05558
4 changed files with 116 additions and 45 deletions

View File

@ -44,6 +44,7 @@
#include <CGAL/Mesh_3/utilities.h> #include <CGAL/Mesh_3/utilities.h>
#include <CGAL/Mesh_3/Triangulation_helpers.h> #include <CGAL/Mesh_3/Triangulation_helpers.h>
#include <CGAL/iterator.h> #include <CGAL/iterator.h>
#include <CGAL/Mesh_error_code.h>
#if CGAL_MESH_3_PROTECTION_DEBUG #if CGAL_MESH_3_PROTECTION_DEBUG
# include <CGAL/Mesh_3/Dump_c3t3.h> # include <CGAL/Mesh_3/Dump_c3t3.h>
#endif #endif
@ -55,6 +56,7 @@
#include <CGAL/iterator.h> #include <CGAL/iterator.h>
#include <CGAL/number_utils.h> #include <CGAL/number_utils.h>
#include <CGAL/Delaunay_triangulation_3.h> #include <CGAL/Delaunay_triangulation_3.h>
#include <CGAL/atomic.h>
#include <CGAL/boost/iterator/transform_iterator.hpp> #include <CGAL/boost/iterator/transform_iterator.hpp>
@ -148,7 +150,13 @@ public:
Protect_edges_sizing_field(C3T3& c3t3, Protect_edges_sizing_field(C3T3& c3t3,
const MeshDomain& domain, const MeshDomain& domain,
SizingFunction size=SizingFunction(), 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<bool>* stop_ptr = 0
#endif
);
void operator()(const bool refine = true); void operator()(const bool refine = true);
@ -156,6 +164,27 @@ public:
nonlinear_growth_of_balls = b; 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: private:
typedef std::vector<std::pair<Curve_index,Bare_point> > Incident_edges; typedef std::vector<std::pair<Curve_index,Bare_point> > Incident_edges;
typedef std::vector<Vertex_handle> Vertex_vector; typedef std::vector<Vertex_handle> Vertex_vector;
@ -440,13 +469,25 @@ private:
Vertex_set unchecked_vertices_; Vertex_set unchecked_vertices_;
int refine_balls_iteration_nb; int refine_balls_iteration_nb;
bool nonlinear_growth_of_balls; 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<bool>* const stop_ptr_;
#endif
}; };
template <typename C3T3, typename MD, typename Sf> template <typename C3T3, typename MD, typename Sf>
Protect_edges_sizing_field<C3T3, MD, Sf>:: Protect_edges_sizing_field<C3T3, MD, Sf>::
Protect_edges_sizing_field(C3T3& c3t3, const MD& domain, 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<bool>* stop_ptr
#endif
)
: c3t3_(c3t3) : c3t3_(c3t3)
, domain_(domain) , domain_(domain)
, size_(size) , size_(size)
@ -454,6 +495,11 @@ Protect_edges_sizing_field(C3T3& c3t3, const MD& domain,
, minimal_weight_(CGAL::square(minimal_size)) , minimal_weight_(CGAL::square(minimal_size))
, refine_balls_iteration_nb(0) , refine_balls_iteration_nb(0)
, nonlinear_growth_of_balls(false) , 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 #ifndef CGAL_MESH_3_NO_PROTECTION_NON_LINEAR
set_nonlinear_growth_of_balls(); set_nonlinear_growth_of_balls();
@ -491,7 +537,7 @@ operator()(const bool refine)
#endif #endif
// Solve problems // Solve problems
if ( refine ) if ( refine && !forced_stop())
{ {
refine_balls(); refine_balls();
#ifdef CGAL_MESH_3_VERBOSE #ifdef CGAL_MESH_3_VERBOSE
@ -523,6 +569,7 @@ insert_corners()
for ( typename Initial_corners::iterator it = corners.begin(), for ( typename Initial_corners::iterator it = corners.begin(),
end = corners.end() ; it != end ; ++it ) end = corners.end() ; it != end ; ++it )
{ {
if(forced_stop()) break;
const Bare_point& p = it->second; const Bare_point& p = it->second;
dt.insert(p); dt.insert(p);
} }
@ -530,6 +577,7 @@ insert_corners()
for ( typename Initial_corners::iterator cit = corners.begin(), for ( typename Initial_corners::iterator cit = corners.begin(),
end = corners.end() ; cit != end ; ++cit ) end = corners.end() ; cit != end ; ++cit )
{ {
if(forced_stop()) break;
const Bare_point& p = cit->second; const Bare_point& p = cit->second;
Index p_index = domain_.index_from_corner_index(cit->first); 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(), for ( typename Input_features::iterator fit = input_features.begin(),
end = input_features.end() ; fit != end ; ++fit ) end = input_features.end() ; fit != end ; ++fit )
{ {
if(forced_stop()) break;
const Curve_index& curve_index = CGAL::cpp11::get<0>(*fit); const Curve_index& curve_index = CGAL::cpp11::get<0>(*fit);
if ( ! is_treated(curve_index) ) if ( ! is_treated(curve_index) )
{ {
@ -1277,6 +1326,7 @@ refine_balls()
while ( (!unchecked_vertices_.empty() || restart) && while ( (!unchecked_vertices_.empty() || restart) &&
this->refine_balls_iteration_nb < refine_balls_max_nb_of_loops) this->refine_balls_iteration_nb < refine_balls_max_nb_of_loops)
{ {
if(forced_stop()) break;
#ifdef CGAL_MESH_3_DUMP_FEATURES_PROTECTION_ITERATIONS #ifdef CGAL_MESH_3_DUMP_FEATURES_PROTECTION_ITERATIONS
std::ostringstream oss; std::ostringstream oss;
oss << "dump_protecting_balls_" << refine_balls_iteration_nb << ".cgal"; 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(), for(typename Tr::Finite_edges_iterator eit = tr.finite_edges_begin(),
end = tr.finite_edges_end(); eit != end; ++eit) end = tr.finite_edges_end(); eit != end; ++eit)
{ {
if(forced_stop()) break;
const Vertex_handle& va = eit->first->vertex(eit->second); const Vertex_handle& va = eit->first->vertex(eit->second);
const Vertex_handle& vb = eit->first->vertex(eit->third); 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 std::map with Vertex_handle as the key is not robust, because
// the time stamp of vertices can change during the following loop. The // the time stamp of vertices can change during the following loop. The
@ -1356,6 +1408,7 @@ refine_balls()
end = new_sizes_copy.end(); end = new_sizes_copy.end();
it != end ; ++it ) it != end ; ++it )
{ {
if(forced_stop()) break;
const Vertex_handle v = it->first; const Vertex_handle v = it->first;
const FT new_size = it->second; const FT new_size = it->second;
// Set size of the ball to new value // Set size of the ball to new value
@ -1379,8 +1432,10 @@ refine_balls()
dump_c3t3_edges(c3t3_, "dump-before-check_and_repopulate_edges"); dump_c3t3_edges(c3t3_, "dump-before-check_and_repopulate_edges");
#endif #endif
// Check edges // Check edges
if(!forced_stop()) {
check_and_repopulate_edges(); check_and_repopulate_edges();
} }
}
if(this->refine_balls_iteration_nb == refine_balls_max_nb_of_loops) if(this->refine_balls_iteration_nb == refine_balls_max_nb_of_loops)
std::cerr << "Warning : features protection has reached maximal " std::cerr << "Warning : features protection has reached maximal "
@ -1553,6 +1608,7 @@ check_and_repopulate_edges()
// Fix edges // Fix edges
while ( !vertices.empty() ) while ( !vertices.empty() )
{ {
if(forced_stop()) break;
Vertex_handle v = *vertices.begin(); Vertex_handle v = *vertices.begin();
vertices.erase(vertices.begin()); vertices.erase(vertices.begin());

View File

@ -203,7 +203,11 @@ void init_c3t3_with_features(C3T3& c3t3,
typedef Edge_criteria_sizing_field_wrapper<Edge_criteria> Sizing_field; typedef Edge_criteria_sizing_field_wrapper<Edge_criteria> Sizing_field;
CGAL::Mesh_3::Protect_edges_sizing_field<C3T3,MeshDomain,Sizing_field> CGAL::Mesh_3::Protect_edges_sizing_field<C3T3,MeshDomain,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.set_nonlinear_growth_of_balls(nonlinear);
protect_edges(true); 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 // Not calling 'init_c3t3_with_features' directly to leave it as a free function
// outside of the C3T3_initializer class // outside of the C3T3_initializer class
virtual void initialize_features(C3T3& c3t3, virtual void
initialize_features(C3T3& c3t3,
const MeshDomain& domain, const MeshDomain& domain,
const MeshCriteria& criteria, const MeshCriteria& criteria,
bool nonlinear = false) 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 > template < typename C3T3, typename MD, typename MC, typename HasFeatures >
struct C3t3_initializer < C3T3, MD, MC, false, HasFeatures > struct C3t3_initializer < C3T3, MD, MC, false, HasFeatures >
{ {
typedef parameters::internal::Mesh_3_options Mesh_3_options;
void operator()(C3T3& c3t3, void operator()(C3T3& c3t3,
const MD& domain, const MD& domain,
const MC& criteria, const MC& criteria,
bool with_features, bool with_features,
bool /* nonlinear */= false, Mesh_3_options mesh_options = Mesh_3_options())
const int nb_initial_points = -1)
{ {
if ( with_features ) if ( with_features )
{ {
@ -257,7 +264,8 @@ struct C3t3_initializer < C3T3, MD, MC, false, HasFeatures >
<< " without features !" << std::endl; << " 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 > template < typename C3T3, typename MD, typename MC, typename HasFeatures >
struct C3t3_initializer < C3T3, MD, MC, true, HasFeatures > struct C3t3_initializer < C3T3, MD, MC, true, HasFeatures >
{ {
typedef parameters::internal::Mesh_3_options Mesh_3_options;
void operator()(C3T3& c3t3, void operator()(C3T3& c3t3,
const MD& domain, const MD& domain,
const MC& criteria, const MC& criteria,
bool with_features, bool with_features,
bool nonlinear = false, Mesh_3_options mesh_options = Mesh_3_options())
const int nb_initial_points = -1)
{ {
C3t3_initializer < C3T3, MD, MC, true, typename MD::Has_features >() 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() { } virtual ~C3t3_initializer() { }
typedef parameters::internal::Mesh_3_options Mesh_3_options;
void operator()(C3T3& c3t3, void operator()(C3T3& c3t3,
const MD& domain, const MD& domain,
const MC& criteria, const MC& criteria,
bool with_features, bool with_features,
bool nonlinear = false, Mesh_3_options mesh_options = Mesh_3_options())
const int nb_initial_points = -1)
{ {
if ( with_features ) { 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 // If c3t3 initialization is not sufficient (may happen if there is only
// a planar curve as feature for example), add some surface points // 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) { 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 > template < typename C3T3, typename MD, typename MC >
struct C3t3_initializer < C3T3, MD, MC, true, CGAL::Tag_false > struct C3t3_initializer < C3T3, MD, MC, true, CGAL::Tag_false >
{ {
typedef parameters::internal::Mesh_3_options Mesh_3_options;
void operator()(C3T3& c3t3, void operator()(C3T3& c3t3,
const MD& domain, const MD& domain,
const MC& criteria, const MC& criteria,
bool with_features, bool with_features,
bool /* nonlinear */ = false, Mesh_3_options mesh_options = Mesh_3_options())
const int nb_initial_points = -1)
{ {
if ( with_features ) if ( with_features )
{ {
@ -336,7 +346,8 @@ struct C3t3_initializer < C3T3, MD, MC, true, CGAL::Tag_false >
<< " without features !" << std::endl; << " 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, domain,
criteria, criteria,
with_features, with_features,
mesh_options.nonlinear_growth_of_balls, mesh_options);
mesh_options.number_of_initial_points);
CGAL_assertion( c3t3.triangulation().dimension() == 3 ); CGAL_assertion( c3t3.triangulation().dimension() == 3 );

View File

@ -209,7 +209,10 @@ struct Mesh_3_options {
#else #else
typedef bool* Pointer_to_stop_atomic_boolean_t; typedef bool* Pointer_to_stop_atomic_boolean_t;
#endif #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_init_prefix()
, dump_after_refine_surface_prefix() , dump_after_refine_surface_prefix()
, dump_after_refine_prefix() , dump_after_refine_prefix()
@ -217,7 +220,7 @@ struct Mesh_3_options {
, dump_after_perturb_prefix() , dump_after_perturb_prefix()
, dump_after_exude_prefix() , dump_after_exude_prefix()
, number_of_initial_points(-1) , number_of_initial_points(-1)
, nonlinear_growth_of_balls(false) , nonlinear_growth_of_balls(nonlinear)
, maximal_number_of_vertices(0) , maximal_number_of_vertices(0)
, pointer_to_error_code(0) , pointer_to_error_code(0)
#ifndef CGAL_NO_ATOMIC #ifndef CGAL_NO_ATOMIC

View File

@ -93,8 +93,7 @@ struct C3t3_initializer_base
const MeshDomain& domain, const MeshDomain& domain,
const MeshCriteria& criteria, const MeshCriteria& criteria,
bool with_features, bool with_features,
bool nonlinear = false, const parameters::internal::Mesh_3_options& mesh_options)
const int nb_initial_points = -1)
{ {
c3t3.triangulation().set_domain(domain.bounding_box()); c3t3.triangulation().set_domain(domain.bounding_box());
c3t3.triangulation().insert_dummy_points(); c3t3.triangulation().insert_dummy_points();
@ -102,8 +101,7 @@ struct C3t3_initializer_base
// Call the basic initialization from c3t3, which handles features and // Call the basic initialization from c3t3, which handles features and
// adds a bunch of points on the surface // adds a bunch of points on the surface
Base::operator()(c3t3, domain, criteria, with_features, Base::operator()(c3t3, domain, criteria, with_features, mesh_options);
nonlinear, nb_initial_points);
} }
}; };
@ -119,9 +117,10 @@ struct C3t3_initializer
MeshDomainHasHasFeatures, HasFeatures> Base; MeshDomainHasHasFeatures, HasFeatures> Base;
void operator()(C3T3& c3t3, const MeshDomain& domain, const MeshCriteria& criteria, 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 <typename C3T3,
struct C3t3_initializer<C3T3, MeshDomain, MeshCriteria, true, HasFeatures> struct C3t3_initializer<C3T3, MeshDomain, MeshCriteria, true, HasFeatures>
{ {
void operator()(C3T3& c3t3, const MeshDomain& domain, const MeshCriteria& criteria, 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, MeshDomain, MeshCriteria, true, typename MeshDomain::Has_features>() C3t3_initializer<C3T3, MeshDomain, MeshCriteria, true, typename MeshDomain::Has_features>()
(c3t3, domain, criteria, with_features, nonlinear, nb_initial_points); (c3t3, domain, criteria, with_features, mesh_options);
} }
}; };
@ -152,18 +152,21 @@ struct C3t3_initializer<C3T3, MeshDomain, MeshCriteria, true, CGAL::Tag_true>
virtual ~C3t3_initializer() { } virtual ~C3t3_initializer() { }
// this override will be used when initialize_features() is called, in make_mesh_3.h // this override will be used when initialize_features() is called, in make_mesh_3.h
virtual void initialize_features(C3T3& c3t3, virtual void
initialize_features(C3T3& c3t3,
const MeshDomain& domain, const MeshDomain& domain,
const MeshCriteria& criteria, const MeshCriteria& criteria,
bool nonlinear = false) 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, 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, domain,
criteria, criteria,
with_features, with_features,
mesh_options.nonlinear_growth_of_balls, mesh_options);
mesh_options.number_of_initial_points);
// Build mesher and launch refinement process // Build mesher and launch refinement process
refine_periodic_3_mesh_3(c3t3, domain, criteria, refine_periodic_3_mesh_3(c3t3, domain, criteria,